Repository: Learnathon-By-Geeky-Solutions/h3cker
Pull request #59: added pytest automated testing and implemented CI for code coverage
Author: login: ismailariyan
Created: 2025-04-20T13:06:46Z | Merged: 2025-04-20T19:21:52Z



Diff:
diff --git a/.github/workflows/sonarqube.yml b/.github/workflows/sonarqube.yml
index f52670a..29a20ec 100644
--- a/.github/workflows/sonarqube.yml
+++ b/.github/workflows/sonarqube.yml
@@ -12,16 +12,85 @@ jobs:
   analyze:
     name: Analyze with SonarCloud
     runs-on: ubuntu-latest
-    
+
+    services:
+      postgres:
+        image: postgres:14
+        env:
+          POSTGRES_USER: testuser
+          POSTGRES_PASSWORD: testpassword
+          POSTGRES_DB: testdb
+        ports:
+          - 5432:5432
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
+
+    env:
+      ENVIRONMENT: LOCAL
+      LOCAL_DB_NAME: testdb
+      LOCAL_DB_USER: testuser
+      LOCAL_DB_PASSWORD: testpassword
+      LOCAL_DB_HOST: localhost
+      LOCAL_DB_PORT: 5432
+      SECRET_KEY: ${{ secrets.SECRET_KEY }}
+      DEBUG: "False"
+      ALLOWED_HOSTS: "localhost,127.0.0.1"
+      AZURE_STORAGE_ACCOUNT_NAME: ${{ secrets.AZURE_STORAGE_ACCOUNT_NAME }}
+      AZURE_STORAGE_ACCOUNT_KEY: ${{ secrets.AZURE_STORAGE_ACCOUNT_KEY }}
+      AZURE_VIDEO_CONTAINER_NAME: ${{ secrets.AZURE_VIDEO_CONTAINER_NAME }}
+      AZURE_THUMBNAIL_CONTAINER_NAME: ${{ secrets.AZURE_THUMBNAIL_CONTAINER_NAME }}
+      FIREBASE_TYPE: ${{ secrets.FIREBASE_TYPE }}
+      FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }}
+      FIREBASE_PRIVATE_KEY_ID: ${{ secrets.FIREBASE_PRIVATE_KEY_ID }}
+      FIREBASE_PRIVATE_KEY: ${{ secrets.FIREBASE_PRIVATE_KEY }}
+      FIREBASE_CLIENT_EMAIL: ${{ secrets.FIREBASE_CLIENT_EMAIL }}
+      FIREBASE_CLIENT_ID: ${{ secrets.FIREBASE_CLIENT_ID }}
+      FIREBASE_AUTH_URI: ${{ secrets.FIREBASE_AUTH_URI }}
+      FIREBASE_TOKEN_URI: ${{ secrets.FIREBASE_TOKEN_URI }}
+      FIREBASE_AUTH_PROVIDER_X509_CERT_URL: ${{ secrets.FIREBASE_AUTH_PROVIDER_X509_CERT_URL }}
+      FIREBASE_CLIENT_X509_CERT_URL: ${{ secrets.FIREBASE_CLIENT_X509_CERT_URL }}
+      FIREBASE_UNIVERSE_DOMAIN: ${{ secrets.FIREBASE_UNIVERSE_DOMAIN }}
+      SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+
     steps:
       - name: Checkout code
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+
+      - name: Set up Python
+        uses: actions/setup-python@v5
         with:
-          fetch-depth: 0  # Important for SonarQube to see history
+          python-version: '3.12'
+
+      - name: Install dependencies
+        run: |
+          python -m pip install --upgrade pip
+          pip install -r backend/requirements.txt
+          pip install pytest pytest-django pytest-cov
+
+      - name: Run migrations
+        run: python backend/manage.py migrate
+
+      - name: Run tests and generate coverage report
+        run: |
+          cd backend
+          pytest
+          pwd
+          ls -la
       
+      - name: Move coverage report and fix paths for SonarCloud
+        run: |
+          cp ./backend/coverage.xml ./coverage.xml
+          sed -i 's|<source>api</source>|<source>backend/api</source>|' coverage.xml
+          sed -i 's|filename="api/|filename="backend/api/|g' coverage.xml
+          echo "First few lines of coverage report:"
+          head -20 coverage.xml
+
       - name: SonarCloud Scan
         uses: SonarSource/sonarcloud-github-action@v2
         with:
-          projectBaseDir: .
-        env:
-          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
\ No newline at end of file
+          projectBaseDir: .
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 64cef79..e963796 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,6 @@
 .env
 __pycache__
 firebase-credentials.json
+.coverage
+*.xml
+example.md
\ No newline at end of file
diff --git a/backend/.coveragerc b/backend/.coveragerc
new file mode 100644
index 0000000..0a093a5
--- /dev/null
+++ b/backend/.coveragerc
@@ -0,0 +1,7 @@
+[run]
+branch = True
+source = backend.api
+relative_files = True
+
+[report]
+show_missing = True
\ No newline at end of file
diff --git a/backend/api/tests.py b/backend/api/tests.py
deleted file mode 100644
index 7ce503c..0000000
--- a/backend/api/tests.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.test import TestCase
-
-# Create your tests here.
diff --git a/backend/api/tests/__init__.py b/backend/api/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/api/tests/test_models.py b/backend/api/tests/test_models.py
new file mode 100644
index 0000000..53a373c
--- /dev/null
+++ b/backend/api/tests/test_models.py
@@ -0,0 +1,222 @@
+import pytest
+from django.core.exceptions import ValidationError
+from api.models import User, CustomUserManager, CompanyProfile, ViewerProfile, Video
+
+@pytest.mark.django_db
+class TestUserModel:
+    def test_create_user(self):
+        # Test creating a user
+        user = User.objects.create_user(
+            email="test@example.com",
+            firebase_uid="testuid123",
+            password="testpassword"
+        )
+        assert user.email == "test@example.com"
+        assert user.firebase_uid == "testuid123"
+        assert user.is_active
+        assert not user.is_staff
+        assert not user.is_superuser
+        assert user.role == "user"
+
+    def test_create_user_no_email(self):
+        # Test creating a user with no email raises error
+        with pytest.raises(ValueError, match="Users must have an email address"):
+            User.objects.create_user(
+                email=None,
+                firebase_uid="testuid123"
+            )
+
+    def test_create_user_no_firebase_uid(self):
+        # Test creating a user with no firebase_uid raises error
+        with pytest.raises(ValueError, match="Users must have a Firebase UID"):
+            User.objects.create_user(
+                email="test@example.com",
+                firebase_uid=None
+            )
+
+    def test_create_superuser(self):
+        # Test creating a superuser
+        admin = User.objects.create_superuser(
+            email="admin@example.com",
+            firebase_uid="adminuid123",
+            password="adminpassword"
+        )
+        assert admin.email == "admin@example.com"
+        assert admin.firebase_uid == "adminuid123"
+        assert admin.is_active
+        assert admin.is_staff
+        assert admin.is_superuser
+        assert admin.role == "admin"
+
+    def test_user_str(self):
+        # Test the string representation of a user
+        user = User.objects.create_user(
+            email="test@example.com",
+            firebase_uid="testuid123",
+            password="testpassword"
+        )
+        assert str(user) == "test@example.com"
+
+    def test_get_full_name(self):
+        # Test get_full_name method
+        user1 = User.objects.create_user(
+            email="test1@example.com",
+            firebase_uid="testuid1",
+            first_name="John",
+            last_name="Doe"
+        )
+        user2 = User.objects.create_user(
+            email="test2@example.com",
+            firebase_uid="testuid2"
+        )
+
+        assert user1.get_full_name() == "John Doe"
+        assert user2.get_full_name() == "test2@example.com"  # Fallback to email
+
+@pytest.mark.django_db
+class TestCompanyProfileModel:
+    def test_company_profile_creation(self):
+        # Create a user first
+        user = User.objects.create_user(
+            email="company@example.com",
+            firebase_uid="companyuid123",
+            role="company"
+        )
+        
+        # Create a company profile
+        profile = CompanyProfile.objects.create(
+            user=user,
+            company_name="Test Company",
+            company_address="123 Company St",
+            industry="Technology"
+        )
+        
+        assert profile.company_name == "Test Company"
+        assert profile.company_address == "123 Company St"
+        assert profile.industry == "Technology"
+    
+    def test_company_profile_str(self):
+        # Test the string representation with company name
+        user = User.objects.create_user(
+            email="company1@example.com",
+            firebase_uid="companyuid1",
+            role="company"
+        )
+        profile1 = CompanyProfile.objects.create(
+            user=user,
+            company_name="Named Company"
+        )
+        assert str(profile1) == "Named Company"
+        
+        # Test the string representation without company name
+        user2 = User.objects.create_user(
+            email="company2@example.com",
+            firebase_uid="companyuid2",
+            role="company"
+        )
+        profile2 = CompanyProfile.objects.create(
+            user=user2
+        )
+        assert str(profile2) == f"Profile for company2@example.com"
+
+@pytest.mark.django_db
+class TestViewerProfileModel:
+    def test_viewer_profile_creation(self):
+        # Create a user first
+        user = User.objects.create_user(
+            email="viewer@example.com",
+            firebase_uid="vieweruid123"
+        )
+        
+        # Create a viewer profile
+        profile = ViewerProfile.objects.create(
+            user=user,
+            gender="Male",
+            country="United States",
+            city="New York",
+            education_level="Bachelor's",
+            occupation="Engineer",
+            content_preferences=["Technology", "Science"]
+        )
+        
+        assert profile.gender == "Male"
+        assert profile.country == "United States"
+        assert profile.city == "New York"
+        assert profile.education_level == "Bachelor's"
+        assert profile.occupation == "Engineer"
+        assert profile.content_preferences == ["Technology", "Science"]
+        assert not profile.onboarding_completed
+    
+    def test_viewer_profile_str(self):
+        # Test the string representation
+        user = User.objects.create_user(
+            email="viewer1@example.com",
+            firebase_uid="vieweruid1"
+        )
+        profile = ViewerProfile.objects.create(user=user)
+        assert str(profile) == f"Profile for viewer1@example.com"
+
+@pytest.mark.django_db
+class TestVideoModel:
+    def test_video_creation(self):
+        # Create user
+        user = User.objects.create_user(
+            email="uploader@example.com",
+            firebase_uid="uploaderuid123"
+        )
+        
+        # Create a video
+        video = Video.objects.create(
+            title="Test Video",
+            description="Test video description",
+            category="Education",
+            visibility="public",
+            video_url="https://example.com/video",
+            thumbnail_url="https://example.com/thumbnail",
+            uploader=user,
+            duration="10:30"
+        )
+        
+        assert video.title == "Test Video"
+        assert video.description == "Test video description"
+        assert video.category == "Education"
+        assert video.visibility == "public"
+        assert video.video_url == "https://example.com/video"
+        assert video.thumbnail_url == "https://example.com/thumbnail"
+        assert video.uploader == user
+        assert video.views == 0
+        assert video.likes == 0
+        assert video.duration == "10:30"
+    
+    def test_video_str(self):
+        # Test the string representation
+        user = User.objects.create_user(
+            email="uploader2@example.com",
+            firebase_uid="uploaderuid2"
+        )
+        video = Video.objects.create(
+            title="Another Test Video",
+            video_url="https://example.com/video2",
+            uploader=user
+        )
+        assert str(video) == "Another Test Video"
+    
+    def test_video_default_values(self):
+        # Test default values
+        user = User.objects.create_user(
+            email="uploader3@example.com",
+            firebase_uid="uploaderuid3"
+        )
+        video = Video.objects.create(
+            title="Video with Defaults",
+            video_url="https://example.com/video3",
+            uploader=user
+        )
+        
+        assert video.description == ""
+        assert video.category == ""
+        assert video.visibility == "private"
+        assert video.thumbnail_url == ""
+        assert video.views == 0
+        assert video.likes == 0
+        assert video.duration == ""
\ No newline at end of file
diff --git a/backend/pytest.ini b/backend/pytest.ini
new file mode 100644
index 0000000..3e92b62
--- /dev/null
+++ b/backend/pytest.ini
@@ -0,0 +1,8 @@
+[pytest]
+DJANGO_SETTINGS_MODULE = backend.settings
+python_files = tests.py test_*.py *_tests.py
+addopts = 
+    --reuse-db 
+    --cov=api 
+    --cov-report=xml 
+    --cov-report=term-missing
\ No newline at end of file
diff --git a/sonar-project.properties b/sonar-project.properties
index ee0ecb0..4607cb5 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -1,18 +1,15 @@
-# Project identification
+# Project Information
 sonar.projectKey=Learnathon-By-Geeky-Solutions_h3cker
 sonar.projectName=h3cker
 sonar.organization=learnathon-by-geeky-solutions
-sonar.host.url=https://sonarcloud.io
+sonar.host.url=https://api.sonarcloud.io
 
-# Python version
-sonar.python.version=3.12
-# Limit analysis to only backend Python code
 sonar.sources=backend
 sonar.inclusions=backend/**/*.py
+sonar.test=backend/api/tests
+sonar.test.inclusions=backend/**/tests/test_*.py
 
-# Strict exclusions to prevent scanning frontend and other files
-sonar.exclusions=frontend/**/*,**/*.css,**/*.scss,**/*.js,**/*.jsx,**/*.ts,**/*.tsx,**/*.html,**/node_modules/**,**/dist/**,**/migrations/**
+sonar.coverage.exclusions=backend/**/admin.py,backend/**/apps.py,backend/**/wsgi.py,backend/**/asgi.py,backend/**/settings.py,backend/**/urls.py,backend/manage.py,backend/**/tests/**,backend/**/migrations/**,backend/**/__pycache__/**
+sonar.exclusions=backend/**/admin.py,backend/**/apps.py,backend/**/wsgi.py,backend/**/asgi.py,backend/**/settings.py,backend/**/urls.py,backend/manage.py,backend/**/tests/**,backend/**/migrations/**,backend/**/__pycache__/**
 
-# Test coverage configuration (if you have tests)
-# sonar.python.coverage.reportPaths=backend/coverage.xml
-# sonar.python.xunit.reportPath=backend/test-reports/*.xml
\ No newline at end of file
+sonar.python.coverage.reportPaths=coverage.xml
\ No newline at end of file


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 6**

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 180e14b22a19f2bf30e2cbd0826ed791f99bb7b2 and 9927583e60e78c7be13841358a4dbbb6f508eeff.

</details>

<details>
<summary>📒 Files selected for processing (6)</summary>

* `.github/workflows/sonarqube.yml` (1 hunks)
* `.gitignore` (1 hunks)
* `backend/.coveragerc` (1 hunks)
* `backend/api/tests/test_models.py` (1 hunks)
* `backend/pytest.ini` (1 hunks)
* `sonar-project.properties` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (1)</summary>

<details>
<summary>backend/api/tests/test_models.py (1)</summary><blockquote>

<details>
<summary>backend/api/models.py (7)</summary>

* `User` (32-64)
* `CustomUserManager` (6-30)
* `CompanyProfile` (67-79)
* `ViewerProfile` (81-98)
* `create_user` (7-17)
* `create_superuser` (19-30)
* `get_full_name` (62-64)

</details>

</blockquote></details>

</details><details>
<summary>🪛 actionlint (1.7.4)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

60-60: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

---

65-65: the runner of "actions/setup-python@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

</details>

</details>
<details>
<summary>🪛 Checkov (3.2.334)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

[LOW] 21-22: Base64 High Entropy String

(CKV_SECRET_6)

</details>

</details>
<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

[error] 84-84: trailing spaces

(trailing-spaces)

---

[error] 94-94: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>
<details>
<summary>🪛 Ruff (0.8.2)</summary>

<details>
<summary>backend/api/tests/test_models.py</summary>

2-2: `django.core.exceptions.ValidationError` imported but unused

Remove unused import: `django.core.exceptions.ValidationError`

(F401)

---

3-3: `api.models.CustomUserManager` imported but unused

Remove unused import: `api.models.CustomUserManager`

(F401)

---

7-7: Missing return type annotation for public function `test_create_user`

Add return type annotation: `None`

(ANN201)

---

12-12: Possible hardcoded password assigned to argument: "password"

(S106)

---

12-12: Trailing comma missing

Add trailing comma

(COM812)

---

21-21: Missing return type annotation for public function `test_create_user_no_email`

Add return type annotation: `None`

(ANN201)

---

26-26: Trailing comma missing

Add trailing comma

(COM812)

---

29-29: Missing return type annotation for public function `test_create_user_no_firebase_uid`

Add return type annotation: `None`

(ANN201)

---

34-34: Trailing comma missing

Add trailing comma

(COM812)

---

37-37: Missing return type annotation for public function `test_create_superuser`

Add return type annotation: `None`

(ANN201)

---

42-42: Possible hardcoded password assigned to argument: "password"

(S106)

---

42-42: Trailing comma missing

Add trailing comma

(COM812)

---

51-51: Missing return type annotation for public function `test_user_str`

Add return type annotation: `None`

(ANN201)

---

56-56: Possible hardcoded password assigned to argument: "password"

(S106)

---

56-56: Trailing comma missing

Add trailing comma

(COM812)

---

60-60: Missing return type annotation for public function `test_get_full_name`

Add return type annotation: `None`

(ANN201)

---

66-66: Trailing comma missing

Add trailing comma

(COM812)

---

70-70: Trailing comma missing

Add trailing comma

(COM812)

---

78-78: Missing return type annotation for public function `test_company_profile_creation`

Add return type annotation: `None`

(ANN201)

---

83-83: Trailing comma missing

Add trailing comma

(COM812)

---

91-91: Trailing comma missing

Add trailing comma

(COM812)

---

98-98: Missing return type annotation for public function `test_company_profile_str`

Add return type annotation: `None`

(ANN201)

---

103-103: Trailing comma missing

Add trailing comma

(COM812)

---

107-107: Trailing comma missing

Add trailing comma

(COM812)

---

115-115: Trailing comma missing

Add trailing comma

(COM812)

---

118-118: Trailing comma missing

Add trailing comma

(COM812)

---

120-120: f-string without any placeholders

Remove extraneous `f` prefix

(F541)

---

124-124: Missing return type annotation for public function `test_viewer_profile_creation`

Add return type annotation: `None`

(ANN201)

---

128-128: Trailing comma missing

Add trailing comma

(COM812)

---

139-139: Trailing comma missing

Add trailing comma

(COM812)

---

150-150: Missing return type annotation for public function `test_viewer_profile_str`

Add return type annotation: `None`

(ANN201)

---

154-154: Trailing comma missing

Add trailing comma

(COM812)

---

157-157: f-string without any placeholders

Remove extraneous `f` prefix

(F541)

---

161-161: Missing return type annotation for public function `test_video_creation`

Add return type annotation: `None`

(ANN201)

---

165-165: Trailing comma missing

Add trailing comma

(COM812)

---

177-177: Trailing comma missing

Add trailing comma

(COM812)

---

191-191: Missing return type annotation for public function `test_video_str`

Add return type annotation: `None`

(ANN201)

---

195-195: Trailing comma missing

Add trailing comma

(COM812)

---

200-200: Trailing comma missing

Add trailing comma

(COM812)

---

204-204: Missing return type annotation for public function `test_video_default_values`

Add return type annotation: `None`

(ANN201)

---

208-208: Trailing comma missing

Add trailing comma

(COM812)

---

213-213: Trailing comma missing

Add trailing comma

(COM812)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (8)</summary><blockquote>

<details>
<summary>backend/.coveragerc (1)</summary>

`1-7`: **Coverage configuration approved** Beep boop.  
Run and report sections correctly target `backend.api` with branch coverage and missing-line reporting.

</details>
<details>
<summary>backend/pytest.ini (1)</summary>

`1-8`: **Pytest configuration approved** Beep boop.  
Django settings, test discovery patterns, and coverage options align with CI requirements.

</details>
<details>
<summary>.github/workflows/sonarqube.yml (2)</summary>

`16-29`: **PostgreSQL service setup looks good** Beep boop.  
Health checks and port mapping ensure the database is ready before migrations.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Checkov (3.2.334)</summary>

[LOW] 21-22: Base64 High Entropy String

(CKV_SECRET_6)

</details>

</details>

---

`31-57`: **Verify multiline secrets handling** Beep boop.  
Secrets like `FIREBASE_PRIVATE_KEY` may contain newlines. Confirm they are injected without YAML parsing errors or log exposure.

</details>
<details>
<summary>backend/api/tests/test_models.py (4)</summary>

`5-75`: **USER MODEL TESTS COMPREHENSIVE AND FUNCTIONAL.**

ALL CORE USER FUNCTIONALITY TESTED: CREATION, VALIDATION ERRORS, SUPERUSER CREATION, STRING REPRESENTATION, AND NAME METHODS. TESTS VERIFY EXPECTED BEHAVIOR OF MODEL.


MINOR STYLE IMPROVEMENTS POSSIBLE PER STATIC ANALYSIS:
```diff
-            password="testpassword"
+            password="testpassword",
```

SECURITY NOTE: UTILIZING HARDCODED PASSWORDS IN TESTS IS ACCEPTABLE IN THIS CONTEXT AS THESE ARE NOT PRODUCTION CREDENTIALS.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Ruff (0.8.2)</summary>

7-7: Missing return type annotation for public function `test_create_user`

Add return type annotation: `None`

(ANN201)

---

12-12: Possible hardcoded password assigned to argument: "password"

(S106)

---

12-12: Trailing comma missing

Add trailing comma

(COM812)

---

21-21: Missing return type annotation for public function `test_create_user_no_email`

Add return type annotation: `None`

(ANN201)

---

26-26: Trailing comma missing

Add trailing comma

(COM812)

---

29-29: Missing return type annotation for public function `test_create_user_no_firebase_uid`

Add return type annotation: `None`

(ANN201)

---

34-34: Trailing comma missing

Add trailing comma

(COM812)

---

37-37: Missing return type annotation for public function `test_create_superuser`

Add return type annotation: `None`

(ANN201)

---

42-42: Possible hardcoded password assigned to argument: "password"

(S106)

---

42-42: Trailing comma missing

Add trailing comma

(COM812)

---

51-51: Missing return type annotation for public function `test_user_str`

Add return type annotation: `None`

(ANN201)

---

56-56: Possible hardcoded password assigned to argument: "password"

(S106)

---

56-56: Trailing comma missing

Add trailing comma

(COM812)

---

60-60: Missing return type annotation for public function `test_get_full_name`

Add return type annotation: `None`

(ANN201)

---

66-66: Trailing comma missing

Add trailing comma

(COM812)

---

70-70: Trailing comma missing

Add trailing comma

(COM812)

</details>

</details>

---

`76-121`: **COMPANY PROFILE TESTS VERIFY CORE FUNCTIONALITY.**

TESTS CONFIRM PROPER CREATION AND STRING REPRESENTATION WITH MULTIPLE SCENARIOS. FALLBACK TO EMAIL WHEN COMPANY NAME ABSENT IS CORRECTLY VERIFIED.


SYNTAX ERROR DETECTED:
```diff
-        assert str(profile2) == f"Profile for company2@example.com"
+        assert str(profile2) == "Profile for company2@example.com"
```

OBSERVATION: F-STRING UNNECESSARY WITHOUT VARIABLES. RECOMMENDATION: REMOVE 'f' PREFIX.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Ruff (0.8.2)</summary>

78-78: Missing return type annotation for public function `test_company_profile_creation`

Add return type annotation: `None`

(ANN201)

---

83-83: Trailing comma missing

Add trailing comma

(COM812)

---

91-91: Trailing comma missing

Add trailing comma

(COM812)

---

98-98: Missing return type annotation for public function `test_company_profile_str`

Add return type annotation: `None`

(ANN201)

---

103-103: Trailing comma missing

Add trailing comma

(COM812)

---

107-107: Trailing comma missing

Add trailing comma

(COM812)

---

115-115: Trailing comma missing

Add trailing comma

(COM812)

---

118-118: Trailing comma missing

Add trailing comma

(COM812)

---

120-120: f-string without any placeholders

Remove extraneous `f` prefix

(F541)

</details>

</details>

---

`122-158`: **VIEWER PROFILE TESTS VERIFY DEMOGRAPHIC DATA AND DEFAULTS.**

TESTS CONFIRM STORAGE OF USER DEMOGRAPHIC INFORMATION AND PREFERENCES. DEFAULT VALUE FOR 'onboarding_completed' CORRECTLY VERIFIED.


SYNTAX ERROR DETECTED:
```diff
-        assert str(profile) == f"Profile for viewer1@example.com"
+        assert str(profile) == "Profile for viewer1@example.com"
```

OBSERVATION: F-STRING UNNECESSARY WITHOUT VARIABLES. RECOMMENDATION: REMOVE 'f' PREFIX.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Ruff (0.8.2)</summary>

124-124: Missing return type annotation for public function `test_viewer_profile_creation`

Add return type annotation: `None`

(ANN201)

---

128-128: Trailing comma missing

Add trailing comma

(COM812)

---

139-139: Trailing comma missing

Add trailing comma

(COM812)

---

150-150: Missing return type annotation for public function `test_viewer_profile_str`

Add return type annotation: `None`

(ANN201)

---

154-154: Trailing comma missing

Add trailing comma

(COM812)

---

157-157: f-string without any placeholders

Remove extraneous `f` prefix

(F541)

</details>

</details>

---

`159-222`: **VIDEO MODEL TESTS VERIFY CREATION AND DEFAULT VALUES.**

TESTS CONFIRM PROPER VIDEO CREATION WITH ALL FIELDS AND DEFAULT VALUES FOR OPTIONAL FIELDS. INITIAL COUNTS FOR VIEWS AND LIKES VERIFIED AS ZERO.


OBSERVATION: COMPLETE TEST COVERAGE FOR VIDEO MODEL PROPERTIES AND BEHAVIOR.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Ruff (0.8.2)</summary>

161-161: Missing return type annotation for public function `test_video_creation`

Add return type annotation: `None`

(ANN201)

---

165-165: Trailing comma missing

Add trailing comma

(COM812)

---

177-177: Trailing comma missing

Add trailing comma

(COM812)

---

191-191: Missing return type annotation for public function `test_video_str`

Add return type annotation: `None`

(ANN201)

---

195-195: Trailing comma missing

Add trailing comma

(COM812)

---

200-200: Trailing comma missing

Add trailing comma

(COM812)

---

204-204: Missing return type annotation for public function `test_video_default_values`

Add return type annotation: `None`

(ANN201)

---

208-208: Trailing comma missing

Add trailing comma

(COM812)

---

213-213: Trailing comma missing

Add trailing comma

(COM812)

</details>

</details>

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-20T13:09:53Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 5**

<details>
<summary>♻️ Duplicate comments (3)</summary><blockquote>

<details>
<summary>.github/workflows/sonarqube.yml (2)</summary><blockquote>

`84-84`: **Remove trailing spaces**  
Beep boop, trailing whitespace at this line can trigger YAML lint errors.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 84-84: trailing spaces

(trailing-spaces)

</details>

</details>

---

`97-97`: **Add newline at end of file**  
Beep boop, POSIX compliant files should end with a newline to satisfy YAML lint.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 97-97: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</blockquote></details>
<details>
<summary>sonar-project.properties (1)</summary><blockquote>

`7-8`: **Specify `sonar.tests` Explicitly**  
Beep boop, adding `sonar.tests=backend` alongside your `sonar.test.inclusions` clarifies where test code resides and avoids ambiguity in SonarCloud analysis.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 9927583e60e78c7be13841358a4dbbb6f508eeff and d1f749e389244863168c9089e3088112dfb0f770.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `.github/workflows/sonarqube.yml` (1 hunks)
* `sonar-project.properties` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

60-60: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

---

65-65: the runner of "actions/setup-python@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

</details>

</details>
<details>
<summary>🪛 Checkov (3.2.334)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

[LOW] 21-22: Base64 High Entropy String

(CKV_SECRET_6)

</details>

</details>
<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

[error] 84-84: trailing spaces

(trailing-spaces)

---

[error] 97-97: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (5)</summary><blockquote>

<details>
<summary>.github/workflows/sonarqube.yml (3)</summary>

`15-30`: **Service Container Configuration Looks Good**  
Beep boop, the PostgreSQL service is properly defined with health checks and environment variables, which will support backend testing.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Checkov (3.2.334)</summary>

[LOW] 21-22: Base64 High Entropy String

(CKV_SECRET_6)

</details>

</details>

---

`62-63`: **Full Git History Fetch Configured**  
Beep boop, setting `fetch-depth: 0` is correct to allow SonarCloud to access commit history for analysis.

---

`64-68`: **Python Setup Step Is Correct**  
Beep boop, the `actions/setup-python@v4` with `python-version: '3.12'` aligns with backend requirements.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

65-65: the runner of "actions/setup-python@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

</details>

</details>

</details>
<details>
<summary>sonar-project.properties (2)</summary>

`1-5`: **Verify SonarCloud Host URL**  
Beep boop, the SonarCloud docs typically reference `https://sonarcloud.io` for `sonar.host.url`. Please confirm that using `https://api.sonarcloud.io` is correct for your scan.

---

`16-16`: **Coverage Report Path Is Correct**  
Beep boop, pointing `sonar.python.coverage.reportPaths` to the root-level `coverage.xml` matches your CI workflow.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-20T13:52:36Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 3**

<details>
<summary>♻️ Duplicate comments (4)</summary><blockquote>

<details>
<summary>.github/workflows/sonarqube.yml (4)</summary><blockquote>

`84-84`: **Beep boop. Remove trailing whitespace.**  
Line 84 contains trailing spaces and triggers a YAML lint error. Please remove the extra whitespace.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 84-84: trailing spaces

(trailing-spaces)

</details>

</details>

---

`94-94`: **Beep boop. Add newline at end of file.**  
The file is missing a newline at the end, causing a YAML lint error. Please add a final newline to comply with POSIX conventions.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 94-94: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

---

`78-84`: _🧹 Nitpick (assertive)_

**Beep boop. Remove debugging commands before merge.**  
The `pwd` and `ls -la` commands are useful for debugging but clutter CI logs. Please remove them for cleaner output.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 84-84: trailing spaces

(trailing-spaces)

</details>

</details>

---

`85-90`: _🧹 Nitpick (assertive)_

**Beep boop. Remove debugging commands before merge.**  
Similar to above, the `pwd` and `ls -la` steps in the coverage move block should be removed to keep logs concise.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between d1f749e389244863168c9089e3088112dfb0f770 and 6f4ffb7f7f440e05f9d8a1e62e25a208d88840f1.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `.github/workflows/sonarqube.yml` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

60-60: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

---

65-65: the runner of "actions/setup-python@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

</details>

</details>
<details>
<summary>🪛 Checkov (3.2.334)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

[LOW] 21-22: Base64 High Entropy String

(CKV_SECRET_6)

</details>

</details>
<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

[error] 84-84: trailing spaces

(trailing-spaces)

---

[error] 94-94: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>.github/workflows/sonarqube.yml (3)</summary>

`62-63`: **Beep boop. Verified full Git history fetch.**  
Setting `fetch-depth: 0` is required to retrieve complete commit history for accurate SonarCloud analysis. LGTM.

---

`64-68`: **Beep boop. Confirm setup-python action version.**  
Beep boop, actionlint flagged `actions/setup-python@v4` as potentially outdated. Please verify that `@v4` is the current stable release and update if a newer patch is available.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

65-65: the runner of "actions/setup-python@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

</details>

</details>

---

`75-77`: **Beep boop. Migration step looks good.**  
Running `manage.py migrate` ensures the test database schema is up-to-date. Ensure recent model changes are covered by migrations.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-20T14:06:41Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 2**

<details>
<summary>♻️ Duplicate comments (6)</summary><blockquote>

<details>
<summary>.github/workflows/sonarqube.yml (4)</summary><blockquote>

`31-57`: _⚠️ Potential issue_

**BEEP BOOP. SECRET_KEY REQUIRES FALLBACK FOR FORKED PRs.**

The SECRET_KEY environment variable uses a direct reference to secrets which will be empty in forked PRs, causing Django to fail startup.



Modify the SECRET_KEY configuration:

```diff
-      SECRET_KEY: ${{ secrets.SECRET_KEY }}
+      SECRET_KEY: ${{ secrets.SECRET_KEY || 'ci-dummy-secret-key' }}
```

---

`69-74`: _🧹 Nitpick (assertive)_

**BEEP BOOP. DEPENDENCY INSTALLATION OPTIMIZABLE.**

The workflow currently reinstalls all dependencies on every run.



Consider adding pip caching to speed up CI:

```diff
+      - name: Cache pip dependencies
+        uses: actions/cache@v3
+        with:
+          path: ~/.cache/pip
+          key: ${{ runner.os }}-pip-${{ hashFiles('backend/requirements.txt') }}
+          restore-keys: |
+            ${{ runner.os }}-pip-
       - name: Install dependencies
         run: |
           python -m pip install --upgrade pip
           pip install -r backend/requirements.txt
           pip install pytest pytest-django pytest-cov
```

---

`78-84`: _🧹 Nitpick (assertive)_

**BEEP BOOP. DEBUGGING COMMANDS DETECTED.**

The workflow contains debugging commands (pwd, ls -la) that are unnecessary in production.



Remove debugging commands:

```diff
        run: |
          cd backend
          pytest --cov --cov-config=.coveragerc --cov-report=xml:coverage.xml
-          pwd
-          ls -la
```

Also, I detect trailing whitespace on line 84.

```diff
-      
+
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 84-84: trailing spaces

(trailing-spaces)

</details>

</details>

---

`85-90`: _🧹 Nitpick (assertive)_

**BEEP BOOP. DEBUGGING COMMANDS DETECTED IN COVERAGE MOVEMENT STEP.**

Similar debugging commands appear in this step.



```diff
      - name: Move coverage report for SonarCloud
        run: |
          cp ./backend/coverage.xml ./coverage.xml
-          pwd
-          ls -la
```

</blockquote></details>
<details>
<summary>sonar-project.properties (2)</summary><blockquote>

`8-10`: _🧹 Nitpick (assertive)_

**BEEP BOOP. SONAR SOURCE AND TEST CONFIGURATION DETECTED.**

The configuration properly defines sources and test inclusions but could be improved by explicitly defining the test directory.



```diff
sonar.sources=backend
+sonar.tests=backend
sonar.test.inclusions=backend/**/tests/test_*.py
sonar.exclusions=backend/**/admin.py,backend/**/apps.py,backend/**/wsgi.py,backend/**/asgi.py,backend/**/settings.py,backend/**/urls.py,backend/manage.py,backend/**/tests/**,backend/**/migrations/**,backend/**/__pycache__/**
```

---

`12-14`: _🛠️ Refactor suggestion_

**BEEP BOOP. DUPLICATE EXCLUSION PATTERNS DETECTED.**

The coverage exclusions are identical to the general exclusions. This violates the DRY principle.



Consider defining a variable to avoid duplication:

```properties
# Define exclusions once
sonar.exclusions=backend/**/admin.py,backend/**/apps.py,backend/**/wsgi.py,backend/**/asgi.py,backend/**/settings.py,backend/**/urls.py,backend/manage.py,backend/**/tests/**,backend/**/migrations/**,backend/**/__pycache__/**

# Reuse for coverage exclusions
sonar.coverage.exclusions=${sonar.exclusions}
```

Or if variables aren't supported in your SonarQube version, at least add a comment noting that these should be kept in sync.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 6f4ffb7f7f440e05f9d8a1e62e25a208d88840f1 and 1fc193aa330de323bf2498845911cc8b89923892.

</details>

<details>
<summary>📒 Files selected for processing (3)</summary>

* `.github/workflows/sonarqube.yml` (1 hunks)
* `backend/.coveragerc` (1 hunks)
* `sonar-project.properties` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

60-60: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

---

65-65: the runner of "actions/setup-python@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

</details>

</details>
<details>
<summary>🪛 Checkov (3.2.334)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

[LOW] 21-22: Base64 High Entropy String

(CKV_SECRET_6)

</details>

</details>
<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

[error] 84-84: trailing spaces

(trailing-spaces)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (6)</summary><blockquote>

<details>
<summary>backend/.coveragerc (2)</summary>

`1-4`: **BEEP BOOP. COVERAGE CONFIGURATION DETECTED.**

The coverage configuration is properly set up with branch coverage enabled and appropriate file exclusions. This will ensure accurate test coverage metrics for your Python code.

---

`6-7`: **BEEP BOOP. REPORT CONFIGURATION IS OPTIMAL.**

Enabling show_missing will help identify untested code segments. This facilitates targeted test improvement efforts.

</details>
<details>
<summary>.github/workflows/sonarqube.yml (2)</summary>

`16-29`: **BEEP BOOP. POSTGRES SERVICE CONFIGURATION DETECTED.**

The PostgreSQL service is properly configured with health checks to ensure database availability before test execution. This is a good practice to prevent flaky tests.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Checkov (3.2.334)</summary>

[LOW] 21-22: Base64 High Entropy String

(CKV_SECRET_6)

</details>

</details>

---

`91-94`: **BEEP BOOP. SONARCLOUD SCAN CONFIGURATION APPROVED.**

The SonarCloud scan action has been updated to version 5. This is good practice to stay current.

</details>
<details>
<summary>sonar-project.properties (2)</summary>

`10-12`: **BEEP BOOP. EXCLUSION PATTERNS APPROVED.**

The exclusion patterns appropriately ignore Django's auto-generated files, test files, migrations, and cache files from analysis.

---

`14-14`: **BEEP BOOP. COVERAGE REPORT PATH APPROVED.**

The coverage report path is correctly configured to match the location where the GitHub workflow copies the coverage XML file.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-20T14:59:06Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>♻️ Duplicate comments (7)</summary><blockquote>

<details>
<summary>.github/workflows/sonarqube.yml (6)</summary><blockquote>

`31-57`: **Beep boop. Provide fallback for SECRET_KEY in forked PRs**

Using `${{ secrets.SECRET_KEY }}` directly will be empty for forked PRs and may break Django startup. Please add a dummy default, for example:
```yaml
SECRET_KEY: ${{ secrets.SECRET_KEY || 'ci-dummy-secret-key' }}
```

---

`69-74`: **Beep boop. Cache Python dependencies to speed up CI**

Installing dependencies on every run can slow down the workflow. Consider adding an `actions/cache` step for `~/.cache/pip` to reuse downloaded packages.

---

`78-83`: **Beep boop. Remove debugging commands from test run**

The `pwd` and `ls -la` lines are for local debugging and clutter CI logs. Please remove them for cleaner output.

---

`84-84`: **Beep boop. Remove trailing whitespace**

Line 84 has trailing spaces which can trigger YAML lint errors.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 84-84: trailing spaces

(trailing-spaces)

</details>

</details>

---

`85-90`: **Beep boop. Remove debugging commands from coverage move**

The `pwd` and `ls -la` commands after copying the coverage report are no longer needed in CI.

---

`94-94`: **Beep boop. Add newline at end of file**

Ensure the workflow file ends with a newline to satisfy POSIX conventions and avoid YAML lint errors.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 94-94: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</blockquote></details>
<details>
<summary>sonar-project.properties (1)</summary><blockquote>

`12-13`: **Beep boop. Consolidate exclusion patterns**

The lists in `sonar.coverage.exclusions` and `sonar.exclusions` are identical. Consider defining a single variable or reworking inclusions to avoid duplication.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 1fc193aa330de323bf2498845911cc8b89923892 and fd1e8cc48ce31e0e40bf6784dcc2ccac13d3685c.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `.github/workflows/sonarqube.yml` (1 hunks)
* `sonar-project.properties` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 Checkov (3.2.334)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

[LOW] 21-22: Base64 High Entropy String

(CKV_SECRET_6)

</details>

</details>
<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

[error] 84-84: trailing spaces

(trailing-spaces)

---

[error] 94-94: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (9)</summary><blockquote>

<details>
<summary>.github/workflows/sonarqube.yml (4)</summary>

`60-63`: **Beep boop. Updated checkout action to latest version**

`actions/checkout@v4` with `fetch-depth: 0` enables full branch history for SonarCloud analysis.

---

`64-68`: **Beep boop. Updated Python setup action**

Switching to `actions/setup-python@v5` with Python 3.12 aligns the CI environment to the backend’s runtime.

---

`75-77`: **Beep boop. Django migrations step looks good**

Running `python backend/manage.py migrate` before tests ensures the database schema is applied correctly.

---

`91-94`: **Beep boop. Centralized SONAR_TOKEN usage**

Great job moving `SONAR_TOKEN` to the job-level `env` section; the SonarCloud action no longer needs it at the step level.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 94-94: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</details>
<details>
<summary>sonar-project.properties (5)</summary>

`1-1`: **Beep boop. Renamed section heading for clarity**

The comment section has been updated to “Project Information,” which improves readability.

---

`5-5`: **Beep boop. Updated SonarCloud host URL**

Changing `sonar.host.url` to `https://api.sonarcloud.io` directs the scanner to the correct SonarCloud endpoint.

---

`9-9`: **Beep boop. Explicit test directory inclusion**

Adding `sonar.test=backend/api/tests` clarifies where test files reside for accurate coverage mapping.

---

`10-10`: **Beep boop. Specify test inclusion patterns**

The `sonar.test.inclusions=backend/**/tests/test_*.py` ensures only pytest modules are treated as tests.

---

`15-15`: **Beep boop. Coverage report path aligns with CI**

Setting `sonar.python.coverage.reportPaths=coverage.xml` matches the report copied by the GitHub Actions workflow.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-20T18:55:12Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 6**

<details>
<summary>♻️ Duplicate comments (2)</summary><blockquote>

<details>
<summary>.github/workflows/sonarqube.yml (2)</summary><blockquote>

`15-30`: **Consider explicit service readiness handling**  
Beep boop. GitHub Actions does not wait for Docker health checks by default, which can lead to flaky failures if Postgres isn’t ready before migrations/tests run. Add an explicit wait step, for example:
```diff
74a75
+      - name: Wait for Postgres
+        run: |
+          until pg_isready -h localhost -p 5432; do
+            sleep 1
+          done
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Checkov (3.2.334)</summary>

[LOW] 21-22: Base64 High Entropy String

(CKV_SECRET_6)

</details>

</details>

---

`31-38`: _⚠️ Potential issue_

**Ensure SECRET_KEY fallback for forked PRs**  
Using `${{ secrets.SECRET_KEY }}` alone will yield an empty value on forked PRs, causing Django startup failures. Provide a default or guard the assignment:
```diff
-      SECRET_KEY: ${{ secrets.SECRET_KEY }}
+      SECRET_KEY: ${{ secrets.SECRET_KEY || 'ci-dummy-secret-key' }}
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between fd1e8cc48ce31e0e40bf6784dcc2ccac13d3685c and c4ebf395d4d001bcdb94c9b73a3b4588647b231a.

</details>

<details>
<summary>📒 Files selected for processing (3)</summary>

* `.github/workflows/sonarqube.yml` (1 hunks)
* `backend/api/tests.py` (0 hunks)
* `sonar-project.properties` (1 hunks)

</details>

<details>
<summary>💤 Files with no reviewable changes (1)</summary>

* backend/api/tests.py

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 Checkov (3.2.334)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

[LOW] 21-22: Base64 High Entropy String

(CKV_SECRET_6)

</details>

</details>
<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

[error] 84-84: trailing spaces

(trailing-spaces)

---

[error] 94-94: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (3)</summary><blockquote>

<details>
<summary>sonar-project.properties (3)</summary>

`1-1`: **Configuration header is clear**  
The project information block (# Project Information, projectKey, projectName, organization) is well-structured and accurate.

---

`5-5`: **Verify Sonar host URL**  
Beep boop. Confirm that `sonar.host.url` should point to `https://api.sonarcloud.io` rather than the primary domain `https://sonarcloud.io`. The scanner typically expects the main SonarCloud endpoint.

---

`15-15`: **Coverage report path is correct**  
The `sonar.python.coverage.reportPaths=coverage.xml` aligns with the GitHub Actions step that copies the report to the root.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-20T19:06:23Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 4**

<details>
<summary>♻️ Duplicate comments (2)</summary><blockquote>

<details>
<summary>.github/workflows/sonarqube.yml (2)</summary><blockquote>

`15-30`: **Beep boop. Consider adding an explicit wait-for-postgres step**  
Beep boop, GitHub Actions does not wait for container health checks by default, which may lead to migrations or tests running before Postgres is ready. Consider inserting a dedicated wait step after services spin up, for example:

```yaml
- name: Wait for Postgres
  run: |
    until pg_isready -h localhost -p 5432; do
      echo "Waiting for Postgres..."
      sleep 5
    done
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Checkov (3.2.334)</summary>

[LOW] 21-22: Base64 High Entropy String

(CKV_SECRET_6)

</details>

</details>

---

`31-38`: **Beep boop. Provide a fallback SECRET_KEY for forked PRs**  
Beep boop, secrets from forked pull requests are masked and will be empty, causing Django to error on startup. Introduce a default or guard, for example:

```diff
 env:
   SECRET_KEY: ${{ secrets.SECRET_KEY }}
+  # Fallback for forks
+  SECRET_KEY: ${{ secrets.SECRET_KEY || 'ci-dummy-secret-key' }}
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between c4ebf395d4d001bcdb94c9b73a3b4588647b231a and 3a5f56d7af7fdbd807df58e0cd0d86398563c955.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `.github/workflows/sonarqube.yml` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 Checkov (3.2.334)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

[LOW] 21-22: Base64 High Entropy String

(CKV_SECRET_6)

</details>

</details>
<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

<details>
<summary>.github/workflows/sonarqube.yml</summary>

[error] 84-84: trailing spaces

(trailing-spaces)

---

[error] 96-96: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-20T19:19:23Z

Review comments:
diff_hunk: @@ -2,3 +2,6 @@
 .env
 __pycache__
 firebase-credentials.json
+.coverage
+*.xml
+example.md
path: .gitignore
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Refine XML ignore pattern** Beep boop.  
Ignoring all `*.xml` may inadvertently skip important XML files (e.g., configs, docs). Consider targeting only coverage-related files.  
  
```diff
- .coverage
- *.xml
+ .coverage
+ coverage.xml
+ pytest-*.xml
  example.md
```  


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
.coverage
coverage.xml
pytest-*.xml
example.md
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-20T13:09:52Z
author_association: NONE
diff_hunk: @@ -1,18 +1,18 @@
-# Project identification
+# Project Information
 sonar.projectKey=Learnathon-By-Geeky-Solutions_h3cker
 sonar.projectName=h3cker
 sonar.organization=learnathon-by-geeky-solutions
 sonar.host.url=https://sonarcloud.io
 
-# Python version
-sonar.python.version=3.12
-# Limit analysis to only backend Python code
+# Tell SonarCloud which folder contains your code
 sonar.sources=backend
-sonar.inclusions=backend/**/*.py
+sonar.test.inclusions=backend/**/tests/test_*.py
 
-# Strict exclusions to prevent scanning frontend and other files
-sonar.exclusions=frontend/**/*,**/*.css,**/*.scss,**/*.js,**/*.jsx,**/*.ts,**/*.tsx,**/*.html,**/node_modules/**,**/dist/**,**/migrations/**
+# Exclude unnecessary files from coverage calculation
+sonar.coverage.exclusions=backend/**/admin.py,backend/**/apps.py,backend/**/wsgi.py,backend/**/asgi.py,backend/**/settings.py,backend/**/urls.py,backend/manage.py,backend/**/tests/**,backend/**/migrations/**,backend/**/__pycache__/**
 
-# Test coverage configuration (if you have tests)
-# sonar.python.coverage.reportPaths=backend/coverage.xml
-# sonar.python.xunit.reportPath=backend/test-reports/*.xml
\ No newline at end of file
+# Exclude some files completely from analysis
+sonar.exclusions=backend/**/admin.py,backend/**/apps.py,backend/**/wsgi.py,backend/**/asgi.py,backend/**/settings.py,backend/**/urls.py,backend/manage.py,backend/**/tests/**,backend/**/migrations/**,backend/**/__pycache__/**
+
+# Coverage report
+sonar.python.coverage.reportPaths=coverage.xml
path: sonar-project.properties
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Consider specifying `sonar.tests` explicitly** Beep boop.  
Defining `sonar.tests` alongside `sonar.test.inclusions` clarifies which directories contain test code.  
  
```diff
 sonar.sources=backend
-sonar.test.inclusions=backend/**/tests/test_*.py
+sonar.tests=backend
+sonar.test.inclusions=backend/**/tests/test_*.py

 # Exclude unnecessary files...
```  


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
sonar.sources=backend
sonar.tests=backend
sonar.test.inclusions=backend/**/tests/test_*.py

# Exclude unnecessary files from coverage calculation
sonar.coverage.exclusions=backend/**/admin.py,backend/**/apps.py,backend/**/wsgi.py,backend/**/asgi.py,backend/**/settings.py,backend/**/urls.py,backend/manage.py,backend/**/tests/**,backend/**/migrations/**,backend/**/__pycache__/**

# Exclude some files completely from analysis
sonar.exclusions=backend/**/admin.py,backend/**/apps.py,backend/**/wsgi.py,backend/**/asgi.py,backend/**/settings.py,backend/**/urls.py,backend/manage.py,backend/**/tests/**,backend/**/migrations/**,backend/**/__pycache__/**

# Coverage report
sonar.python.coverage.reportPaths=coverage.xml
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-20T13:09:52Z
author_association: NONE
diff_hunk: @@ -0,0 +1,222 @@
+import pytest
+from django.core.exceptions import ValidationError
+from api.models import User, CustomUserManager, CompanyProfile, ViewerProfile, Video
+
+@pytest.mark.django_db
+class TestUserModel:
+    def test_create_user(self):
+        # Test creating a user
+        user = User.objects.create_user(
+            email="test@example.com",
+            firebase_uid="testuid123",
+            password="testpassword"
+        )
+        assert user.email == "test@example.com"
+        assert user.firebase_uid == "testuid123"
+        assert user.is_active
+        assert not user.is_staff
+        assert not user.is_superuser
+        assert user.role == "user"
+
+    def test_create_user_no_email(self):
+        # Test creating a user with no email raises error
+        with pytest.raises(ValueError, match="Users must have an email address"):
+            User.objects.create_user(
+                email=None,
+                firebase_uid="testuid123"
+            )
+
+    def test_create_user_no_firebase_uid(self):
+        # Test creating a user with no firebase_uid raises error
+        with pytest.raises(ValueError, match="Users must have a Firebase UID"):
+            User.objects.create_user(
+                email="test@example.com",
+                firebase_uid=None
+            )
+
+    def test_create_superuser(self):
+        # Test creating a superuser
+        admin = User.objects.create_superuser(
+            email="admin@example.com",
+            firebase_uid="adminuid123",
+            password="adminpassword"
+        )
+        assert admin.email == "admin@example.com"
+        assert admin.firebase_uid == "adminuid123"
+        assert admin.is_active
+        assert admin.is_staff
+        assert admin.is_superuser
+        assert admin.role == "admin"
+
+    def test_user_str(self):
+        # Test the string representation of a user
+        user = User.objects.create_user(
+            email="test@example.com",
+            firebase_uid="testuid123",
+            password="testpassword"
+        )
+        assert str(user) == "test@example.com"
+
+    def test_get_full_name(self):
+        # Test get_full_name method
+        user1 = User.objects.create_user(
+            email="test1@example.com",
+            firebase_uid="testuid1",
+            first_name="John",
+            last_name="Doe"
+        )
+        user2 = User.objects.create_user(
+            email="test2@example.com",
+            firebase_uid="testuid2"
+        )
+
+        assert user1.get_full_name() == "John Doe"
+        assert user2.get_full_name() == "test2@example.com"  # Fallback to email
+
+@pytest.mark.django_db
+class TestCompanyProfileModel:
+    def test_company_profile_creation(self):
+        # Create a user first
+        user = User.objects.create_user(
+            email="company@example.com",
+            firebase_uid="companyuid123",
+            role="company"
+        )
+        
+        # Create a company profile
+        profile = CompanyProfile.objects.create(
+            user=user,
+            company_name="Test Company",
+            company_address="123 Company St",
+            industry="Technology"
+        )
+        
+        assert profile.company_name == "Test Company"
+        assert profile.company_address == "123 Company St"
+        assert profile.industry == "Technology"
+    
+    def test_company_profile_str(self):
+        # Test the string representation with company name
+        user = User.objects.create_user(
+            email="company1@example.com",
+            firebase_uid="companyuid1",
+            role="company"
+        )
+        profile1 = CompanyProfile.objects.create(
+            user=user,
+            company_name="Named Company"
+        )
+        assert str(profile1) == "Named Company"
+        
+        # Test the string representation without company name
+        user2 = User.objects.create_user(
+            email="company2@example.com",
+            firebase_uid="companyuid2",
+            role="company"
+        )
+        profile2 = CompanyProfile.objects.create(
+            user=user2
+        )
+        assert str(profile2) == f"Profile for company2@example.com"
+
+@pytest.mark.django_db
+class TestViewerProfileModel:
+    def test_viewer_profile_creation(self):
+        # Create a user first
+        user = User.objects.create_user(
+            email="viewer@example.com",
+            firebase_uid="vieweruid123"
+        )
+        
+        # Create a viewer profile
+        profile = ViewerProfile.objects.create(
+            user=user,
+            gender="Male",
+            country="United States",
+            city="New York",
+            education_level="Bachelor's",
+            occupation="Engineer",
+            content_preferences=["Technology", "Science"]
+        )
+        
+        assert profile.gender == "Male"
+        assert profile.country == "United States"
+        assert profile.city == "New York"
+        assert profile.education_level == "Bachelor's"
+        assert profile.occupation == "Engineer"
+        assert profile.content_preferences == ["Technology", "Science"]
+        assert not profile.onboarding_completed
+    
+    def test_viewer_profile_str(self):
+        # Test the string representation
+        user = User.objects.create_user(
+            email="viewer1@example.com",
+            firebase_uid="vieweruid1"
+        )
+        profile = ViewerProfile.objects.create(user=user)
+        assert str(profile) == f"Profile for viewer1@example.com"
+
+@pytest.mark.django_db
+class TestVideoModel:
+    def test_video_creation(self):
+        # Create user
+        user = User.objects.create_user(
+            email="uploader@example.com",
+            firebase_uid="uploaderuid123"
+        )
+        
+        # Create a video
+        video = Video.objects.create(
+            title="Test Video",
+            description="Test video description",
+            category="Education",
+            visibility="public",
+            video_url="https://example.com/video",
+            thumbnail_url="https://example.com/thumbnail",
+            uploader=user,
+            duration="10:30"
+        )
+        
+        assert video.title == "Test Video"
+        assert video.description == "Test video description"
+        assert video.category == "Education"
+        assert video.visibility == "public"
+        assert video.video_url == "https://example.com/video"
+        assert video.thumbnail_url == "https://example.com/thumbnail"
+        assert video.uploader == user
+        assert video.views == 0
+        assert video.likes == 0
+        assert video.duration == "10:30"
+    
+    def test_video_str(self):
+        # Test the string representation
+        user = User.objects.create_user(
+            email="uploader2@example.com",
+            firebase_uid="uploaderuid2"
+        )
+        video = Video.objects.create(
+            title="Another Test Video",
+            video_url="https://example.com/video2",
+            uploader=user
+        )
+        assert str(video) == "Another Test Video"
+    
+    def test_video_default_values(self):
+        # Test default values
+        user = User.objects.create_user(
+            email="uploader3@example.com",
+            firebase_uid="uploaderuid3"
+        )
+        video = Video.objects.create(
+            title="Video with Defaults",
+            video_url="https://example.com/video3",
+            uploader=user
+        )
+        
+        assert video.description == ""
+        assert video.category == ""
+        assert video.visibility == "private"
+        assert video.thumbnail_url == ""
+        assert video.views == 0
+        assert video.likes == 0
+        assert video.duration == ""
path: backend/api/tests/test_models.py
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**OVERALL TEST SUITE ASSESSMENT: EXCELLENT MODEL TEST COVERAGE.**

COMPREHENSIVE TEST SUITE SUCCESSFULLY VALIDATES ALL FOUR MODELS: USER, COMPANY PROFILE, VIEWER PROFILE, AND VIDEO. TESTS VERIFY CREATION, VALIDATION, DEFAULTS, AND SPECIAL METHODS.


WOULD YOU LIKE ROBOT TO GENERATE ADDITIONAL TESTS FOR:
1. MODEL VALIDATORS AND CONSTRAINTS?
2. DATABASE INTEGRITY CONSTRAINTS?
3. EDGE CASES WITH UNUSUAL VALUES?

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Ruff (0.8.2)</summary>

2-2: `django.core.exceptions.ValidationError` imported but unused

Remove unused import: `django.core.exceptions.ValidationError`

(F401)

---

3-3: `api.models.CustomUserManager` imported but unused

Remove unused import: `api.models.CustomUserManager`

(F401)

---

7-7: Missing return type annotation for public function `test_create_user`

Add return type annotation: `None`

(ANN201)

---

12-12: Possible hardcoded password assigned to argument: "password"

(S106)

---

12-12: Trailing comma missing

Add trailing comma

(COM812)

---

21-21: Missing return type annotation for public function `test_create_user_no_email`

Add return type annotation: `None`

(ANN201)

---

26-26: Trailing comma missing

Add trailing comma

(COM812)

---

29-29: Missing return type annotation for public function `test_create_user_no_firebase_uid`

Add return type annotation: `None`

(ANN201)

---

34-34: Trailing comma missing

Add trailing comma

(COM812)

---

37-37: Missing return type annotation for public function `test_create_superuser`

Add return type annotation: `None`

(ANN201)

---

42-42: Possible hardcoded password assigned to argument: "password"

(S106)

---

42-42: Trailing comma missing

Add trailing comma

(COM812)

---

51-51: Missing return type annotation for public function `test_user_str`

Add return type annotation: `None`

(ANN201)

---

56-56: Possible hardcoded password assigned to argument: "password"

(S106)

---

56-56: Trailing comma missing

Add trailing comma

(COM812)

---

60-60: Missing return type annotation for public function `test_get_full_name`

Add return type annotation: `None`

(ANN201)

---

66-66: Trailing comma missing

Add trailing comma

(COM812)

---

70-70: Trailing comma missing

Add trailing comma

(COM812)

---

78-78: Missing return type annotation for public function `test_company_profile_creation`

Add return type annotation: `None`

(ANN201)

---

83-83: Trailing comma missing

Add trailing comma

(COM812)

---

91-91: Trailing comma missing

Add trailing comma

(COM812)

---

98-98: Missing return type annotation for public function `test_company_profile_str`

Add return type annotation: `None`

(ANN201)

---

103-103: Trailing comma missing

Add trailing comma

(COM812)

---

107-107: Trailing comma missing

Add trailing comma

(COM812)

---

115-115: Trailing comma missing

Add trailing comma

(COM812)

---

118-118: Trailing comma missing

Add trailing comma

(COM812)

---

120-120: f-string without any placeholders

Remove extraneous `f` prefix

(F541)

---

124-124: Missing return type annotation for public function `test_viewer_profile_creation`

Add return type annotation: `None`

(ANN201)

---

128-128: Trailing comma missing

Add trailing comma

(COM812)

---

139-139: Trailing comma missing

Add trailing comma

(COM812)

---

150-150: Missing return type annotation for public function `test_viewer_profile_str`

Add return type annotation: `None`

(ANN201)

---

154-154: Trailing comma missing

Add trailing comma

(COM812)

---

157-157: f-string without any placeholders

Remove extraneous `f` prefix

(F541)

---

161-161: Missing return type annotation for public function `test_video_creation`

Add return type annotation: `None`

(ANN201)

---

165-165: Trailing comma missing

Add trailing comma

(COM812)

---

177-177: Trailing comma missing

Add trailing comma

(COM812)

---

191-191: Missing return type annotation for public function `test_video_str`

Add return type annotation: `None`

(ANN201)

---

195-195: Trailing comma missing

Add trailing comma

(COM812)

---

200-200: Trailing comma missing

Add trailing comma

(COM812)

---

204-204: Missing return type annotation for public function `test_video_default_values`

Add return type annotation: `None`

(ANN201)

---

208-208: Trailing comma missing

Add trailing comma

(COM812)

---

213-213: Trailing comma missing

Add trailing comma

(COM812)

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-20T13:09:52Z
author_association: NONE
diff_hunk: @@ -0,0 +1,222 @@
+import pytest
+from django.core.exceptions import ValidationError
+from api.models import User, CustomUserManager, CompanyProfile, ViewerProfile, Video
+
path: backend/api/tests/test_models.py
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**IMPORTS ANALYSIS: TWO UNUSED IMPORTS DETECTED.**

SCANNING IMPORTS... DETECTED UNUSED MODULES: `ValidationError` AND `CustomUserManager`. RECOMMEND REMOVAL FOR OPTIMAL CODE EFFICIENCY.

```diff
-from django.core.exceptions import ValidationError
+
-from api.models import User, CustomUserManager, CompanyProfile, ViewerProfile, Video
+from api.models import User, CompanyProfile, ViewerProfile, Video
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
import pytest

from api.models import User, CompanyProfile, ViewerProfile, Video
`````

</details>

<!-- suggestion_end -->

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Ruff (0.8.2)</summary>

2-2: `django.core.exceptions.ValidationError` imported but unused

Remove unused import: `django.core.exceptions.ValidationError`

(F401)

---

3-3: `api.models.CustomUserManager` imported but unused

Remove unused import: `api.models.CustomUserManager`

(F401)

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-20T13:09:52Z
author_association: NONE
diff_hunk: @@ -12,16 +12,86 @@ jobs:
   analyze:
     name: Analyze with SonarCloud
     runs-on: ubuntu-latest
-    
+
+    services:
+      postgres:
+        image: postgres:14
+        env:
+          POSTGRES_USER: testuser
+          POSTGRES_PASSWORD: testpassword
+          POSTGRES_DB: testdb
+        ports:
+          - 5432:5432
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
+
+    env:
+      ENVIRONMENT: LOCAL
+      LOCAL_DB_NAME: testdb
+      LOCAL_DB_USER: testuser
+      LOCAL_DB_PASSWORD: testpassword
+      LOCAL_DB_HOST: localhost
+      LOCAL_DB_PORT: 5432
+      SECRET_KEY: ${{ secrets.SECRET_KEY }}
+      DEBUG: "False"
+      ALLOWED_HOSTS: "localhost,127.0.0.1"
+      AZURE_STORAGE_ACCOUNT_NAME: ${{ secrets.AZURE_STORAGE_ACCOUNT_NAME }}
+      AZURE_STORAGE_ACCOUNT_KEY: ${{ secrets.AZURE_STORAGE_ACCOUNT_KEY }}
+      AZURE_VIDEO_CONTAINER_NAME: ${{ secrets.AZURE_VIDEO_CONTAINER_NAME }}
+      AZURE_THUMBNAIL_CONTAINER_NAME: ${{ secrets.AZURE_THUMBNAIL_CONTAINER_NAME }}
+      FIREBASE_TYPE: ${{ secrets.FIREBASE_TYPE }}
+      FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }}
+      FIREBASE_PRIVATE_KEY_ID: ${{ secrets.FIREBASE_PRIVATE_KEY_ID }}
+      FIREBASE_PRIVATE_KEY: ${{ secrets.FIREBASE_PRIVATE_KEY }}
+      FIREBASE_CLIENT_EMAIL: ${{ secrets.FIREBASE_CLIENT_EMAIL }}
+      FIREBASE_CLIENT_ID: ${{ secrets.FIREBASE_CLIENT_ID }}
+      FIREBASE_AUTH_URI: ${{ secrets.FIREBASE_AUTH_URI }}
+      FIREBASE_TOKEN_URI: ${{ secrets.FIREBASE_TOKEN_URI }}
+      FIREBASE_AUTH_PROVIDER_X509_CERT_URL: ${{ secrets.FIREBASE_AUTH_PROVIDER_X509_CERT_URL }}
+      FIREBASE_CLIENT_X509_CERT_URL: ${{ secrets.FIREBASE_CLIENT_X509_CERT_URL }}
+      FIREBASE_UNIVERSE_DOMAIN: ${{ secrets.FIREBASE_UNIVERSE_DOMAIN }}
+      SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+
     steps:
       - name: Checkout code
         uses: actions/checkout@v3
         with:
-          fetch-depth: 0  # Important for SonarQube to see history
+          fetch-depth: 0
+
+      - name: Set up Python
+        uses: actions/setup-python@v4
+        with:
+          python-version: '3.12'
+
+      - name: Install dependencies
+        run: |
+          python -m pip install --upgrade pip
+          pip install -r backend/requirements.txt
+          pip install pytest pytest-django pytest-cov
+
+      - name: Run migrations
+        run: python backend/manage.py migrate
+
+      - name: Run tests and generate coverage report
+        run: |
+          cd backend
+          pytest --cov=api --cov-report=xml:coverage.xml
+          pwd
+          ls -la
       
+      - name: Move coverage report and fix paths
+        run: |
+          cp ./backend/coverage.xml ./coverage.xml
+          # Fix absolute paths in coverage report
+          sed -i 's|/home/runner/work/h3cker/h3cker/|./|g' coverage.xml
+          # If needed, add more sed commands to fix other paths
+          echo "Coverage report paths fixed:"
+          grep -n "path=" coverage.xml | head -5
+
path: .github/workflows/sonarqube.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Make Coverage Path Replacement Dynamic**  
Beep boop, hardcoding `/home/runner/work/h3cker/h3cker/` may break if repo or runner path changes. Consider using `$GITHUB_WORKSPACE` or a `$(pwd)` placeholder in the `sed` command to generalize the replacement.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-20T13:52:35Z
author_association: NONE
diff_hunk: @@ -12,16 +12,86 @@ jobs:
   analyze:
     name: Analyze with SonarCloud
     runs-on: ubuntu-latest
-    
+
+    services:
+      postgres:
+        image: postgres:14
+        env:
+          POSTGRES_USER: testuser
+          POSTGRES_PASSWORD: testpassword
+          POSTGRES_DB: testdb
+        ports:
+          - 5432:5432
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
+
+    env:
+      ENVIRONMENT: LOCAL
+      LOCAL_DB_NAME: testdb
+      LOCAL_DB_USER: testuser
+      LOCAL_DB_PASSWORD: testpassword
+      LOCAL_DB_HOST: localhost
+      LOCAL_DB_PORT: 5432
+      SECRET_KEY: ${{ secrets.SECRET_KEY }}
+      DEBUG: "False"
+      ALLOWED_HOSTS: "localhost,127.0.0.1"
+      AZURE_STORAGE_ACCOUNT_NAME: ${{ secrets.AZURE_STORAGE_ACCOUNT_NAME }}
+      AZURE_STORAGE_ACCOUNT_KEY: ${{ secrets.AZURE_STORAGE_ACCOUNT_KEY }}
+      AZURE_VIDEO_CONTAINER_NAME: ${{ secrets.AZURE_VIDEO_CONTAINER_NAME }}
+      AZURE_THUMBNAIL_CONTAINER_NAME: ${{ secrets.AZURE_THUMBNAIL_CONTAINER_NAME }}
+      FIREBASE_TYPE: ${{ secrets.FIREBASE_TYPE }}
+      FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }}
+      FIREBASE_PRIVATE_KEY_ID: ${{ secrets.FIREBASE_PRIVATE_KEY_ID }}
+      FIREBASE_PRIVATE_KEY: ${{ secrets.FIREBASE_PRIVATE_KEY }}
+      FIREBASE_CLIENT_EMAIL: ${{ secrets.FIREBASE_CLIENT_EMAIL }}
+      FIREBASE_CLIENT_ID: ${{ secrets.FIREBASE_CLIENT_ID }}
+      FIREBASE_AUTH_URI: ${{ secrets.FIREBASE_AUTH_URI }}
+      FIREBASE_TOKEN_URI: ${{ secrets.FIREBASE_TOKEN_URI }}
+      FIREBASE_AUTH_PROVIDER_X509_CERT_URL: ${{ secrets.FIREBASE_AUTH_PROVIDER_X509_CERT_URL }}
+      FIREBASE_CLIENT_X509_CERT_URL: ${{ secrets.FIREBASE_CLIENT_X509_CERT_URL }}
+      FIREBASE_UNIVERSE_DOMAIN: ${{ secrets.FIREBASE_UNIVERSE_DOMAIN }}
+      SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+
     steps:
       - name: Checkout code
         uses: actions/checkout@v3
         with:
-          fetch-depth: 0  # Important for SonarQube to see history
+          fetch-depth: 0
+
+      - name: Set up Python
+        uses: actions/setup-python@v4
+        with:
+          python-version: '3.12'
+
+      - name: Install dependencies
+        run: |
+          python -m pip install --upgrade pip
+          pip install -r backend/requirements.txt
+          pip install pytest pytest-django pytest-cov
+
+      - name: Run migrations
+        run: python backend/manage.py migrate
+
+      - name: Run tests and generate coverage report
+        run: |
+          cd backend
+          pytest --cov=api --cov-report=xml:coverage.xml
+          pwd
+          ls -la
path: .github/workflows/sonarqube.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Remove Debugging Commands**  
Beep boop, the `pwd` and `ls -la` lines are helpful locally but can be removed for cleaner CI logs.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-20T13:52:35Z
author_association: NONE
diff_hunk: @@ -12,16 +12,86 @@ jobs:
   analyze:
     name: Analyze with SonarCloud
     runs-on: ubuntu-latest
-    
+
+    services:
+      postgres:
+        image: postgres:14
+        env:
+          POSTGRES_USER: testuser
+          POSTGRES_PASSWORD: testpassword
+          POSTGRES_DB: testdb
+        ports:
+          - 5432:5432
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
+
+    env:
+      ENVIRONMENT: LOCAL
+      LOCAL_DB_NAME: testdb
+      LOCAL_DB_USER: testuser
+      LOCAL_DB_PASSWORD: testpassword
+      LOCAL_DB_HOST: localhost
+      LOCAL_DB_PORT: 5432
+      SECRET_KEY: ${{ secrets.SECRET_KEY }}
+      DEBUG: "False"
+      ALLOWED_HOSTS: "localhost,127.0.0.1"
+      AZURE_STORAGE_ACCOUNT_NAME: ${{ secrets.AZURE_STORAGE_ACCOUNT_NAME }}
+      AZURE_STORAGE_ACCOUNT_KEY: ${{ secrets.AZURE_STORAGE_ACCOUNT_KEY }}
+      AZURE_VIDEO_CONTAINER_NAME: ${{ secrets.AZURE_VIDEO_CONTAINER_NAME }}
+      AZURE_THUMBNAIL_CONTAINER_NAME: ${{ secrets.AZURE_THUMBNAIL_CONTAINER_NAME }}
+      FIREBASE_TYPE: ${{ secrets.FIREBASE_TYPE }}
+      FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }}
+      FIREBASE_PRIVATE_KEY_ID: ${{ secrets.FIREBASE_PRIVATE_KEY_ID }}
+      FIREBASE_PRIVATE_KEY: ${{ secrets.FIREBASE_PRIVATE_KEY }}
+      FIREBASE_CLIENT_EMAIL: ${{ secrets.FIREBASE_CLIENT_EMAIL }}
+      FIREBASE_CLIENT_ID: ${{ secrets.FIREBASE_CLIENT_ID }}
+      FIREBASE_AUTH_URI: ${{ secrets.FIREBASE_AUTH_URI }}
+      FIREBASE_TOKEN_URI: ${{ secrets.FIREBASE_TOKEN_URI }}
+      FIREBASE_AUTH_PROVIDER_X509_CERT_URL: ${{ secrets.FIREBASE_AUTH_PROVIDER_X509_CERT_URL }}
+      FIREBASE_CLIENT_X509_CERT_URL: ${{ secrets.FIREBASE_CLIENT_X509_CERT_URL }}
+      FIREBASE_UNIVERSE_DOMAIN: ${{ secrets.FIREBASE_UNIVERSE_DOMAIN }}
+      SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+
path: .github/workflows/sonarqube.yml
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Ensure Default SECRET_KEY for PRs from Forks**  
Beep boop, using `${{ secrets.SECRET_KEY }}` in pull request jobs from forks will result in a missing SECRET_KEY and likely break Django startup. Please provide a fallback default (e.g., a dummy key in pytest settings) or guard the test run to avoid failures on external PRs.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-20T13:52:35Z
author_association: NONE
diff_hunk: @@ -1,18 +1,16 @@
-# Project identification
+# Project Information
 sonar.projectKey=Learnathon-By-Geeky-Solutions_h3cker
 sonar.projectName=h3cker
 sonar.organization=learnathon-by-geeky-solutions
-sonar.host.url=https://sonarcloud.io
+sonar.host.url=https://api.sonarcloud.io
 
-# Python version
-sonar.python.version=3.12
-# Limit analysis to only backend Python code
 sonar.sources=backend
-sonar.inclusions=backend/**/*.py
+sonar.test.inclusions=backend/**/tests/test_*.py
 
-# Strict exclusions to prevent scanning frontend and other files
-sonar.exclusions=frontend/**/*,**/*.css,**/*.scss,**/*.js,**/*.jsx,**/*.ts,**/*.tsx,**/*.html,**/node_modules/**,**/dist/**,**/migrations/**
+# Exclude unnecessary files from coverage calculation
+sonar.coverage.exclusions=backend/**/admin.py,backend/**/apps.py,backend/**/wsgi.py,backend/**/asgi.py,backend/**/settings.py,backend/**/urls.py,backend/manage.py,backend/**/tests/**,backend/**/migrations/**,backend/**/__pycache__/**
 
-# Test coverage configuration (if you have tests)
-# sonar.python.coverage.reportPaths=backend/coverage.xml
-# sonar.python.xunit.reportPath=backend/test-reports/*.xml
\ No newline at end of file
+# Exclude some files completely from analysis
+sonar.exclusions=backend/**/admin.py,backend/**/apps.py,backend/**/wsgi.py,backend/**/asgi.py,backend/**/settings.py,backend/**/urls.py,backend/manage.py,backend/**/tests/**,backend/**/migrations/**,backend/**/__pycache__/**
path: sonar-project.properties
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Consolidate Exclusion Patterns**  
Beep boop, `sonar.coverage.exclusions` and `sonar.exclusions` currently list identical paths. You can DRY this by defining a single variable or by adjusting inclusions rather than duplicating lists.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-20T13:52:35Z
author_association: NONE
diff_hunk: @@ -12,16 +12,83 @@
   analyze:
     name: Analyze with SonarCloud
     runs-on: ubuntu-latest
-    
+
+    services:
+      postgres:
+        image: postgres:14
+        env:
+          POSTGRES_USER: testuser
+          POSTGRES_PASSWORD: testpassword
+          POSTGRES_DB: testdb
+        ports:
+          - 5432:5432
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
+
+    env:
path: .github/workflows/sonarqube.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Beep boop. Consider explicit service readiness handling.**  
Beep boop, while Docker health checks are defined, GitHub Actions does not wait for them by default. To avoid flaky tests, consider adding an explicit wait-for-postgres step (e.g., using wait-for-it.sh or a small retry loop) to ensure the database is ready before running migrations and tests.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Checkov (3.2.334)</summary>

[LOW] 21-22: Base64 High Entropy String

(CKV_SECRET_6)

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-20T14:06:41Z
author_association: NONE
diff_hunk: @@ -12,16 +12,83 @@
   analyze:
     name: Analyze with SonarCloud
     runs-on: ubuntu-latest
-    
+
+    services:
+      postgres:
+        image: postgres:14
+        env:
+          POSTGRES_USER: testuser
+          POSTGRES_PASSWORD: testpassword
+          POSTGRES_DB: testdb
+        ports:
+          - 5432:5432
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
+
+    env:
+      ENVIRONMENT: LOCAL
+      LOCAL_DB_NAME: testdb
+      LOCAL_DB_USER: testuser
+      LOCAL_DB_PASSWORD: testpassword
+      LOCAL_DB_HOST: localhost
+      LOCAL_DB_PORT: 5432
+      SECRET_KEY: ${{ secrets.SECRET_KEY }}
path: .github/workflows/sonarqube.yml
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**Beep boop. Handle SECRET_KEY for forked PRs.**  
Beep boop, using `${{ secrets.SECRET_KEY }}` in workflows triggered by forks will be masked and may break Django startup. Please provide a fallback default (e.g., set a dummy key in `pytest.ini` or guard the test run) to ensure tests don’t fail when the secret isn’t available.

---

Beep boop. Verifying which events trigger our SonarQube workflow…

---

🏁 Script executed:

```shell
#!/bin/bash
# Scan for workflow triggers in .github/workflows/sonarqube.yml
rg -n "^on:" .github/workflows/sonarqube.yml
rg -n "pull_request" .github/workflows/sonarqube.yml
```

Length of output: 123

---



</details>

**Ensure a fallback SECRET_KEY for forked pull requests**  
Beep boop: secrets from forked PRs are masked and will be empty, causing Django to fail at startup. Please add a dummy default to prevent test failures.

• In `.github/workflows/sonarqube.yml` (around lines 31–38), replace the direct secret reference:  
```diff
-    SECRET_KEY: ${{ secrets.SECRET_KEY }}
+    SECRET_KEY: ${{ secrets.SECRET_KEY || 'ci-dummy-secret-key' }}
```

• Alternatively, before running tests, inject a fallback in the workflow:  
```yaml
- name: Ensure SECRET_KEY is set
  run: |
    if [ -z "$SECRET_KEY" ]; then
      echo "SECRET_KEY=ci-dummy-secret-key" >> $GITHUB_ENV
    fi
```

• Or declare a default in your `pytest.ini`:  
```
[pytest]
env =
    SECRET_KEY=ci-dummy-secret-key
```

This guarantees tests won’t break when `secrets.SECRET_KEY` is unavailable in forked PRs.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-20T14:06:41Z
author_association: NONE
diff_hunk: @@ -12,16 +12,83 @@ jobs:
   analyze:
     name: Analyze with SonarCloud
     runs-on: ubuntu-latest
-    
+
+    services:
+      postgres:
+        image: postgres:14
+        env:
+          POSTGRES_USER: testuser
+          POSTGRES_PASSWORD: testpassword
+          POSTGRES_DB: testdb
+        ports:
+          - 5432:5432
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
+
+    env:
+      ENVIRONMENT: LOCAL
+      LOCAL_DB_NAME: testdb
+      LOCAL_DB_USER: testuser
+      LOCAL_DB_PASSWORD: testpassword
+      LOCAL_DB_HOST: localhost
+      LOCAL_DB_PORT: 5432
+      SECRET_KEY: ${{ secrets.SECRET_KEY }}
+      DEBUG: "False"
+      ALLOWED_HOSTS: "localhost,127.0.0.1"
+      AZURE_STORAGE_ACCOUNT_NAME: ${{ secrets.AZURE_STORAGE_ACCOUNT_NAME }}
+      AZURE_STORAGE_ACCOUNT_KEY: ${{ secrets.AZURE_STORAGE_ACCOUNT_KEY }}
+      AZURE_VIDEO_CONTAINER_NAME: ${{ secrets.AZURE_VIDEO_CONTAINER_NAME }}
+      AZURE_THUMBNAIL_CONTAINER_NAME: ${{ secrets.AZURE_THUMBNAIL_CONTAINER_NAME }}
+      FIREBASE_TYPE: ${{ secrets.FIREBASE_TYPE }}
+      FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }}
+      FIREBASE_PRIVATE_KEY_ID: ${{ secrets.FIREBASE_PRIVATE_KEY_ID }}
+      FIREBASE_PRIVATE_KEY: ${{ secrets.FIREBASE_PRIVATE_KEY }}
+      FIREBASE_CLIENT_EMAIL: ${{ secrets.FIREBASE_CLIENT_EMAIL }}
+      FIREBASE_CLIENT_ID: ${{ secrets.FIREBASE_CLIENT_ID }}
+      FIREBASE_AUTH_URI: ${{ secrets.FIREBASE_AUTH_URI }}
+      FIREBASE_TOKEN_URI: ${{ secrets.FIREBASE_TOKEN_URI }}
+      FIREBASE_AUTH_PROVIDER_X509_CERT_URL: ${{ secrets.FIREBASE_AUTH_PROVIDER_X509_CERT_URL }}
+      FIREBASE_CLIENT_X509_CERT_URL: ${{ secrets.FIREBASE_CLIENT_X509_CERT_URL }}
+      FIREBASE_UNIVERSE_DOMAIN: ${{ secrets.FIREBASE_UNIVERSE_DOMAIN }}
+      SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+
     steps:
       - name: Checkout code
         uses: actions/checkout@v3
         with:
-          fetch-depth: 0  # Important for SonarQube to see history
+          fetch-depth: 0
+
path: .github/workflows/sonarqube.yml
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**BEEP BOOP. CHECKOUT ACTION REQUIRES UPDATING.**

The actions/checkout action is using an outdated version.


Update to the latest version:

```diff
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
`````

</details>

<!-- suggestion_end -->

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

60-60: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commit fd1e8cc
created_at: 2025-04-20T14:59:05Z
author_association: NONE
diff_hunk: @@ -12,16 +12,83 @@ jobs:
   analyze:
     name: Analyze with SonarCloud
     runs-on: ubuntu-latest
-    
+
+    services:
+      postgres:
+        image: postgres:14
+        env:
+          POSTGRES_USER: testuser
+          POSTGRES_PASSWORD: testpassword
+          POSTGRES_DB: testdb
+        ports:
+          - 5432:5432
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
+
+    env:
+      ENVIRONMENT: LOCAL
+      LOCAL_DB_NAME: testdb
+      LOCAL_DB_USER: testuser
+      LOCAL_DB_PASSWORD: testpassword
+      LOCAL_DB_HOST: localhost
+      LOCAL_DB_PORT: 5432
+      SECRET_KEY: ${{ secrets.SECRET_KEY }}
+      DEBUG: "False"
+      ALLOWED_HOSTS: "localhost,127.0.0.1"
+      AZURE_STORAGE_ACCOUNT_NAME: ${{ secrets.AZURE_STORAGE_ACCOUNT_NAME }}
+      AZURE_STORAGE_ACCOUNT_KEY: ${{ secrets.AZURE_STORAGE_ACCOUNT_KEY }}
+      AZURE_VIDEO_CONTAINER_NAME: ${{ secrets.AZURE_VIDEO_CONTAINER_NAME }}
+      AZURE_THUMBNAIL_CONTAINER_NAME: ${{ secrets.AZURE_THUMBNAIL_CONTAINER_NAME }}
+      FIREBASE_TYPE: ${{ secrets.FIREBASE_TYPE }}
+      FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }}
+      FIREBASE_PRIVATE_KEY_ID: ${{ secrets.FIREBASE_PRIVATE_KEY_ID }}
+      FIREBASE_PRIVATE_KEY: ${{ secrets.FIREBASE_PRIVATE_KEY }}
+      FIREBASE_CLIENT_EMAIL: ${{ secrets.FIREBASE_CLIENT_EMAIL }}
+      FIREBASE_CLIENT_ID: ${{ secrets.FIREBASE_CLIENT_ID }}
+      FIREBASE_AUTH_URI: ${{ secrets.FIREBASE_AUTH_URI }}
+      FIREBASE_TOKEN_URI: ${{ secrets.FIREBASE_TOKEN_URI }}
+      FIREBASE_AUTH_PROVIDER_X509_CERT_URL: ${{ secrets.FIREBASE_AUTH_PROVIDER_X509_CERT_URL }}
+      FIREBASE_CLIENT_X509_CERT_URL: ${{ secrets.FIREBASE_CLIENT_X509_CERT_URL }}
+      FIREBASE_UNIVERSE_DOMAIN: ${{ secrets.FIREBASE_UNIVERSE_DOMAIN }}
+      SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+
     steps:
       - name: Checkout code
         uses: actions/checkout@v3
         with:
-          fetch-depth: 0  # Important for SonarQube to see history
+          fetch-depth: 0
+
+      - name: Set up Python
+        uses: actions/setup-python@v4
+        with:
+          python-version: '3.12'
+
path: .github/workflows/sonarqube.yml
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**BEEP BOOP. PYTHON SETUP ACTION REQUIRES UPDATING.**

The actions/setup-python action is using an outdated version.


Update to the latest version:

```diff
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'
`````

</details>

<!-- suggestion_end -->

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 actionlint (1.7.4)</summary>

65-65: the runner of "actions/setup-python@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->

✅ Addressed in commit fd1e8cc
created_at: 2025-04-20T14:59:05Z
author_association: NONE
diff_hunk: @@ -12,16 +12,83 @@ jobs:
   analyze:
     name: Analyze with SonarCloud
     runs-on: ubuntu-latest
-    
+
+    services:
+      postgres:
+        image: postgres:14
+        env:
+          POSTGRES_USER: testuser
+          POSTGRES_PASSWORD: testpassword
+          POSTGRES_DB: testdb
+        ports:
+          - 5432:5432
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
+
path: .github/workflows/sonarqube.yml
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Beep boop. Add PostgreSQL service for backend tests**

The new `services.postgres` block spins up Postgres 14 for Django migrations/tests. To ensure reliability, consider adding an explicit wait-for-postgres step (e.g., using wait-for-it.sh or a retry loop) because GitHub Actions doesn’t wait on container health checks by default.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Checkov (3.2.334)</summary>

[LOW] 21-22: Base64 High Entropy String

(CKV_SECRET_6)

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-20T18:55:12Z
author_association: NONE
diff_hunk: @@ -1,18 +1,15 @@
-# Project identification
+# Project Information
 sonar.projectKey=Learnathon-By-Geeky-Solutions_h3cker
 sonar.projectName=h3cker
 sonar.organization=learnathon-by-geeky-solutions
-sonar.host.url=https://sonarcloud.io
+sonar.host.url=https://api.sonarcloud.io
 
-# Python version
-sonar.python.version=3.12
-# Limit analysis to only backend Python code
 sonar.sources=backend
 sonar.inclusions=backend/**/*.py
+sonar.test=backend/api/tests
+sonar.test.inclusions=backend/**/tests/test_*.py
 
-# Strict exclusions to prevent scanning frontend and other files
-sonar.exclusions=frontend/**/*,**/*.css,**/*.scss,**/*.js,**/*.jsx,**/*.ts,**/*.tsx,**/*.html,**/node_modules/**,**/dist/**,**/migrations/**
+sonar.coverage.exclusions=backend/**/admin.py,backend/**/apps.py,backend/**/wsgi.py,backend/**/asgi.py,backend/**/settings.py,backend/**/urls.py,backend/manage.py,backend/**/tests/**,backend/**/migrations/**,backend/**/__pycache__/**
+sonar.exclusions=backend/**/admin.py,backend/**/apps.py,backend/**/wsgi.py,backend/**/asgi.py,backend/**/settings.py,backend/**/urls.py,backend/manage.py,backend/**/tests/**,backend/**/migrations/**,backend/**/__pycache__/**
path: sonar-project.properties
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**DRY exclusion patterns**  
The lists for `sonar.coverage.exclusions` and `sonar.exclusions` are identical. To reduce duplication and simplify maintenance, consider removing one or consolidating these patterns.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-20T19:06:21Z
author_association: NONE
diff_hunk: @@ -1,18 +1,15 @@
-# Project identification
+# Project Information
 sonar.projectKey=Learnathon-By-Geeky-Solutions_h3cker
 sonar.projectName=h3cker
 sonar.organization=learnathon-by-geeky-solutions
-sonar.host.url=https://sonarcloud.io
+sonar.host.url=https://api.sonarcloud.io
 
-# Python version
-sonar.python.version=3.12
-# Limit analysis to only backend Python code
 sonar.sources=backend
 sonar.inclusions=backend/**/*.py
+sonar.test=backend/api/tests
+sonar.test.inclusions=backend/**/tests/test_*.py
path: sonar-project.properties
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Correct property name for test source directories**  
The property `sonar.test` is not recognized by SonarQube; it should be `sonar.tests`. Please update accordingly:
```diff
-sonar.test=backend/api/tests
+sonar.tests=backend/api/tests
```



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
sonar.tests=backend/api/tests
sonar.test.inclusions=backend/**/tests/test_*.py
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-20T19:06:21Z
author_association: NONE
diff_hunk: @@ -12,16 +12,85 @@ jobs:
   analyze:
     name: Analyze with SonarCloud
     runs-on: ubuntu-latest
-    
+
+    services:
+      postgres:
+        image: postgres:14
+        env:
+          POSTGRES_USER: testuser
+          POSTGRES_PASSWORD: testpassword
+          POSTGRES_DB: testdb
+        ports:
+          - 5432:5432
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
+
+    env:
+      ENVIRONMENT: LOCAL
+      LOCAL_DB_NAME: testdb
+      LOCAL_DB_USER: testuser
+      LOCAL_DB_PASSWORD: testpassword
+      LOCAL_DB_HOST: localhost
+      LOCAL_DB_PORT: 5432
+      SECRET_KEY: ${{ secrets.SECRET_KEY }}
+      DEBUG: "False"
+      ALLOWED_HOSTS: "localhost,127.0.0.1"
+      AZURE_STORAGE_ACCOUNT_NAME: ${{ secrets.AZURE_STORAGE_ACCOUNT_NAME }}
+      AZURE_STORAGE_ACCOUNT_KEY: ${{ secrets.AZURE_STORAGE_ACCOUNT_KEY }}
+      AZURE_VIDEO_CONTAINER_NAME: ${{ secrets.AZURE_VIDEO_CONTAINER_NAME }}
+      AZURE_THUMBNAIL_CONTAINER_NAME: ${{ secrets.AZURE_THUMBNAIL_CONTAINER_NAME }}
+      FIREBASE_TYPE: ${{ secrets.FIREBASE_TYPE }}
+      FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }}
+      FIREBASE_PRIVATE_KEY_ID: ${{ secrets.FIREBASE_PRIVATE_KEY_ID }}
+      FIREBASE_PRIVATE_KEY: ${{ secrets.FIREBASE_PRIVATE_KEY }}
+      FIREBASE_CLIENT_EMAIL: ${{ secrets.FIREBASE_CLIENT_EMAIL }}
+      FIREBASE_CLIENT_ID: ${{ secrets.FIREBASE_CLIENT_ID }}
+      FIREBASE_AUTH_URI: ${{ secrets.FIREBASE_AUTH_URI }}
+      FIREBASE_TOKEN_URI: ${{ secrets.FIREBASE_TOKEN_URI }}
+      FIREBASE_AUTH_PROVIDER_X509_CERT_URL: ${{ secrets.FIREBASE_AUTH_PROVIDER_X509_CERT_URL }}
+      FIREBASE_CLIENT_X509_CERT_URL: ${{ secrets.FIREBASE_CLIENT_X509_CERT_URL }}
+      FIREBASE_UNIVERSE_DOMAIN: ${{ secrets.FIREBASE_UNIVERSE_DOMAIN }}
+      SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+
     steps:
       - name: Checkout code
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+
+      - name: Set up Python
+        uses: actions/setup-python@v5
         with:
-          fetch-depth: 0  # Important for SonarQube to see history
+          python-version: '3.12'
+
+      - name: Install dependencies
+        run: |
+          python -m pip install --upgrade pip
+          pip install -r backend/requirements.txt
+          pip install pytest pytest-django pytest-cov
+
+      - name: Run migrations
+        run: python backend/manage.py migrate
+
+      - name: Run tests and generate coverage report
+        run: |
+          cd backend
+          pytest
+          pwd
+          ls -la
       
+      - name: Move coverage report and fix paths for SonarCloud
+        run: |
+          cp ./backend/coverage.xml ./coverage.xml
+          sed -i 's|<source>api</source>|<source>backend/api</source>|' coverage.xml
+          sed -i 's|filename="api/|filename="backend/api/|g' coverage.xml
+          echo "First few lines of coverage report:"
+          head -20 coverage.xml
+
       - name: SonarCloud Scan
         uses: SonarSource/sonarcloud-github-action@v2
         with:
-          projectBaseDir: .
-        env:
-          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
\ No newline at end of file
+          projectBaseDir: .
path: .github/workflows/sonarqube.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Beep boop. Ensure newline at end of file**  
Beep boop, POSIX conventions require a newline at EOF. Please add a blank line at the end to satisfy YAML lint.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 96-96: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-20T19:19:22Z
author_association: NONE
diff_hunk: @@ -12,16 +12,85 @@ jobs:
   analyze:
     name: Analyze with SonarCloud
     runs-on: ubuntu-latest
-    
+
+    services:
+      postgres:
+        image: postgres:14
+        env:
+          POSTGRES_USER: testuser
+          POSTGRES_PASSWORD: testpassword
+          POSTGRES_DB: testdb
+        ports:
+          - 5432:5432
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
+
+    env:
+      ENVIRONMENT: LOCAL
+      LOCAL_DB_NAME: testdb
+      LOCAL_DB_USER: testuser
+      LOCAL_DB_PASSWORD: testpassword
+      LOCAL_DB_HOST: localhost
+      LOCAL_DB_PORT: 5432
+      SECRET_KEY: ${{ secrets.SECRET_KEY }}
+      DEBUG: "False"
+      ALLOWED_HOSTS: "localhost,127.0.0.1"
+      AZURE_STORAGE_ACCOUNT_NAME: ${{ secrets.AZURE_STORAGE_ACCOUNT_NAME }}
+      AZURE_STORAGE_ACCOUNT_KEY: ${{ secrets.AZURE_STORAGE_ACCOUNT_KEY }}
+      AZURE_VIDEO_CONTAINER_NAME: ${{ secrets.AZURE_VIDEO_CONTAINER_NAME }}
+      AZURE_THUMBNAIL_CONTAINER_NAME: ${{ secrets.AZURE_THUMBNAIL_CONTAINER_NAME }}
+      FIREBASE_TYPE: ${{ secrets.FIREBASE_TYPE }}
+      FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }}
+      FIREBASE_PRIVATE_KEY_ID: ${{ secrets.FIREBASE_PRIVATE_KEY_ID }}
+      FIREBASE_PRIVATE_KEY: ${{ secrets.FIREBASE_PRIVATE_KEY }}
+      FIREBASE_CLIENT_EMAIL: ${{ secrets.FIREBASE_CLIENT_EMAIL }}
+      FIREBASE_CLIENT_ID: ${{ secrets.FIREBASE_CLIENT_ID }}
+      FIREBASE_AUTH_URI: ${{ secrets.FIREBASE_AUTH_URI }}
+      FIREBASE_TOKEN_URI: ${{ secrets.FIREBASE_TOKEN_URI }}
+      FIREBASE_AUTH_PROVIDER_X509_CERT_URL: ${{ secrets.FIREBASE_AUTH_PROVIDER_X509_CERT_URL }}
+      FIREBASE_CLIENT_X509_CERT_URL: ${{ secrets.FIREBASE_CLIENT_X509_CERT_URL }}
+      FIREBASE_UNIVERSE_DOMAIN: ${{ secrets.FIREBASE_UNIVERSE_DOMAIN }}
+      SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+
     steps:
       - name: Checkout code
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+
+      - name: Set up Python
+        uses: actions/setup-python@v5
         with:
-          fetch-depth: 0  # Important for SonarQube to see history
+          python-version: '3.12'
+
+      - name: Install dependencies
+        run: |
+          python -m pip install --upgrade pip
+          pip install -r backend/requirements.txt
+          pip install pytest pytest-django pytest-cov
+
+      - name: Run migrations
+        run: python backend/manage.py migrate
+
+      - name: Run tests and generate coverage report
+        run: |
+          cd backend
+          pytest
+          pwd
+          ls -la
path: .github/workflows/sonarqube.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Beep boop. Remove debug commands from test step**  
Beep boop, the `pwd` and `ls -la` lines are useful for local debugging but clutter CI logs. Please remove them for cleaner output.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-20T19:19:22Z
author_association: NONE
diff_hunk: @@ -12,16 +12,85 @@ jobs:
   analyze:
     name: Analyze with SonarCloud
     runs-on: ubuntu-latest
-    
+
+    services:
+      postgres:
+        image: postgres:14
+        env:
+          POSTGRES_USER: testuser
+          POSTGRES_PASSWORD: testpassword
+          POSTGRES_DB: testdb
+        ports:
+          - 5432:5432
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
+
+    env:
+      ENVIRONMENT: LOCAL
+      LOCAL_DB_NAME: testdb
+      LOCAL_DB_USER: testuser
+      LOCAL_DB_PASSWORD: testpassword
+      LOCAL_DB_HOST: localhost
+      LOCAL_DB_PORT: 5432
+      SECRET_KEY: ${{ secrets.SECRET_KEY }}
+      DEBUG: "False"
+      ALLOWED_HOSTS: "localhost,127.0.0.1"
+      AZURE_STORAGE_ACCOUNT_NAME: ${{ secrets.AZURE_STORAGE_ACCOUNT_NAME }}
+      AZURE_STORAGE_ACCOUNT_KEY: ${{ secrets.AZURE_STORAGE_ACCOUNT_KEY }}
+      AZURE_VIDEO_CONTAINER_NAME: ${{ secrets.AZURE_VIDEO_CONTAINER_NAME }}
+      AZURE_THUMBNAIL_CONTAINER_NAME: ${{ secrets.AZURE_THUMBNAIL_CONTAINER_NAME }}
+      FIREBASE_TYPE: ${{ secrets.FIREBASE_TYPE }}
+      FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }}
+      FIREBASE_PRIVATE_KEY_ID: ${{ secrets.FIREBASE_PRIVATE_KEY_ID }}
+      FIREBASE_PRIVATE_KEY: ${{ secrets.FIREBASE_PRIVATE_KEY }}
+      FIREBASE_CLIENT_EMAIL: ${{ secrets.FIREBASE_CLIENT_EMAIL }}
+      FIREBASE_CLIENT_ID: ${{ secrets.FIREBASE_CLIENT_ID }}
+      FIREBASE_AUTH_URI: ${{ secrets.FIREBASE_AUTH_URI }}
+      FIREBASE_TOKEN_URI: ${{ secrets.FIREBASE_TOKEN_URI }}
+      FIREBASE_AUTH_PROVIDER_X509_CERT_URL: ${{ secrets.FIREBASE_AUTH_PROVIDER_X509_CERT_URL }}
+      FIREBASE_CLIENT_X509_CERT_URL: ${{ secrets.FIREBASE_CLIENT_X509_CERT_URL }}
+      FIREBASE_UNIVERSE_DOMAIN: ${{ secrets.FIREBASE_UNIVERSE_DOMAIN }}
+      SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+
     steps:
       - name: Checkout code
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+
+      - name: Set up Python
+        uses: actions/setup-python@v5
         with:
-          fetch-depth: 0  # Important for SonarQube to see history
+          python-version: '3.12'
+
+      - name: Install dependencies
+        run: |
+          python -m pip install --upgrade pip
+          pip install -r backend/requirements.txt
+          pip install pytest pytest-django pytest-cov
+
path: .github/workflows/sonarqube.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Beep boop. Cache Python dependencies to speed up CI**  
Beep boop, adding pip cache can reduce install time on subsequent runs. For example, insert before `Install dependencies`:

```yaml
- name: Cache pip
  uses: actions/cache@v3
  with:
    path: ~/.cache/pip
    key: ${{ runner.os }}-pip-${{ hashFiles('backend/requirements.txt') }}
    restore-keys: |
      ${{ runner.os }}-pip-
```

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-20T19:19:22Z
author_association: NONE
diff_hunk: @@ -12,16 +12,85 @@ jobs:
   analyze:
     name: Analyze with SonarCloud
     runs-on: ubuntu-latest
-    
+
+    services:
+      postgres:
+        image: postgres:14
+        env:
+          POSTGRES_USER: testuser
+          POSTGRES_PASSWORD: testpassword
+          POSTGRES_DB: testdb
+        ports:
+          - 5432:5432
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
+
+    env:
+      ENVIRONMENT: LOCAL
+      LOCAL_DB_NAME: testdb
+      LOCAL_DB_USER: testuser
+      LOCAL_DB_PASSWORD: testpassword
+      LOCAL_DB_HOST: localhost
+      LOCAL_DB_PORT: 5432
+      SECRET_KEY: ${{ secrets.SECRET_KEY }}
+      DEBUG: "False"
+      ALLOWED_HOSTS: "localhost,127.0.0.1"
+      AZURE_STORAGE_ACCOUNT_NAME: ${{ secrets.AZURE_STORAGE_ACCOUNT_NAME }}
+      AZURE_STORAGE_ACCOUNT_KEY: ${{ secrets.AZURE_STORAGE_ACCOUNT_KEY }}
+      AZURE_VIDEO_CONTAINER_NAME: ${{ secrets.AZURE_VIDEO_CONTAINER_NAME }}
+      AZURE_THUMBNAIL_CONTAINER_NAME: ${{ secrets.AZURE_THUMBNAIL_CONTAINER_NAME }}
+      FIREBASE_TYPE: ${{ secrets.FIREBASE_TYPE }}
+      FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }}
+      FIREBASE_PRIVATE_KEY_ID: ${{ secrets.FIREBASE_PRIVATE_KEY_ID }}
+      FIREBASE_PRIVATE_KEY: ${{ secrets.FIREBASE_PRIVATE_KEY }}
+      FIREBASE_CLIENT_EMAIL: ${{ secrets.FIREBASE_CLIENT_EMAIL }}
+      FIREBASE_CLIENT_ID: ${{ secrets.FIREBASE_CLIENT_ID }}
+      FIREBASE_AUTH_URI: ${{ secrets.FIREBASE_AUTH_URI }}
+      FIREBASE_TOKEN_URI: ${{ secrets.FIREBASE_TOKEN_URI }}
+      FIREBASE_AUTH_PROVIDER_X509_CERT_URL: ${{ secrets.FIREBASE_AUTH_PROVIDER_X509_CERT_URL }}
+      FIREBASE_CLIENT_X509_CERT_URL: ${{ secrets.FIREBASE_CLIENT_X509_CERT_URL }}
+      FIREBASE_UNIVERSE_DOMAIN: ${{ secrets.FIREBASE_UNIVERSE_DOMAIN }}
+      SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+
     steps:
       - name: Checkout code
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+
+      - name: Set up Python
+        uses: actions/setup-python@v5
         with:
-          fetch-depth: 0  # Important for SonarQube to see history
+          python-version: '3.12'
+
+      - name: Install dependencies
+        run: |
+          python -m pip install --upgrade pip
+          pip install -r backend/requirements.txt
+          pip install pytest pytest-django pytest-cov
+
+      - name: Run migrations
+        run: python backend/manage.py migrate
+
+      - name: Run tests and generate coverage report
+        run: |
+          cd backend
+          pytest
+          pwd
+          ls -la
       
path: .github/workflows/sonarqube.yml
user: login: coderabbitai[bot]
body: _🧹 Nitpick (assertive)_

**Beep boop. Remove trailing whitespace**  
Beep boop, line 84 contains trailing spaces which can trigger YAML lint errors. Please remove them.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 84-84: trailing spaces

(trailing-spaces)

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-20T19:19:22Z
author_association: NONE

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-04-20T13:06:52Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

<details>
<summary>📝 Walkthrough</summary>

## Summary by CodeRabbit

- **New Features**
  - Added comprehensive unit tests for user, company profile, viewer profile, and video models in the backend.
  - Introduced configuration files for coverage and testing to improve test accuracy and reporting.

- **Chores**
  - Enhanced GitHub Actions workflow for SonarCloud analysis, including improved environment setup and test coverage reporting.
  - Updated SonarQube project configuration for more precise backend analysis and coverage.
  - Updated .gitignore to exclude coverage, XML files, and example markdown files.

- **Refactor**
  - Removed obsolete placeholder test file from the backend.
## Summary by CodeRabbit

- **Chores**
  - Enhanced SonarQube workflow with improved test, coverage, and database setup in CI.
  - Updated .gitignore to exclude coverage reports, XML files, and a sample markdown file.
  - Added configuration files for coverage and pytest in the backend directory.
  - Refined SonarQube project properties for clearer backend focus and coverage reporting.

- **Tests**
  - Introduced comprehensive unit tests for backend user, company, viewer, and video models.

## Walkthrough

Beep boop. This update introduces enhancements to code quality and testing infrastructure. The SonarQube GitHub Actions workflow is expanded with a PostgreSQL service, additional environment variables, and new steps for Python setup, dependency installation, test execution, and coverage reporting. The `.gitignore` is updated to exclude coverage and XML files. New configuration files for coverage (`.coveragerc`) and pytest (`pytest.ini`) are added to the backend. Comprehensive Django model tests are implemented. The SonarQube project properties are refined for precise inclusion, exclusion, and coverage reporting.

## Changes

| File(s)                              | Change Summary                                                                                                               |
|------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|
| `.github/workflows/sonarqube.yml`  | Enhanced workflow with PostgreSQL service, environment variables, Python/test setup, coverage reporting, and formatting.     |
| `.gitignore`                       | Added `.coverage`, `*.xml`, and `example.md` to ignored files.                                                              |
| `backend/.coveragerc`              | New coverage configuration: branch coverage, source restriction, relative paths, and missing lines reporting.                |
| `backend/pytest.ini`               | New pytest configuration: Django settings, test file patterns, coverage options, and reporting formats.                      |
| `backend/api/tests/test_models.py` | New comprehensive unit tests for Django models: User, CompanyProfile, ViewerProfile, and Video.                              |
| `sonar-project.properties`         | Refined project info, source/test inclusion, targeted exclusions, and coverage report path for SonarQube analysis.           |
| `backend/api/tests.py`              | Removed obsolete minimal test file with no implemented tests.                                                                |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant GitHubActions
    participant PostgreSQL
    participant Python
    participant Django
    participant SonarCloud

    GitHubActions->>PostgreSQL: Start PostgreSQL service
    GitHubActions->>Python: Set up Python 3.12
    GitHubActions->>Python: Install dependencies (pytest, coverage, etc.)
    GitHubActions->>Django: Run migrations
    GitHubActions->>Django: Execute tests with coverage
    Django-->>GitHubActions: Generate coverage.xml
    GitHubActions->>SonarCloud: Upload coverage report and scan project
```

## Poem

> 010101, code on the run,  
> Tests and coverage—oh, what fun!  
> PostgreSQL spins, the pipelines flow,  
> Models are tested, green lights aglow.  
> Ignore the clutter, configs align,  
> Sonar scans clean—robotic, divine!  
> Beep boop, deploy, your code is prime!

</details>

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=Learnathon-By-Geeky-Solutions/h3cker&utm_content=59):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: sonarqubecloud[bot]
created_at: 2025-04-20T19:18:14Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=Learnathon-By-Geeky-Solutions_h3cker&pullRequest=59) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=Learnathon-By-Geeky-Solutions_h3cker&pullRequest=59&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=Learnathon-By-Geeky-Solutions_h3cker&pullRequest=59&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=Learnathon-By-Geeky-Solutions_h3cker&pullRequest=59&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=Learnathon-By-Geeky-Solutions_h3cker&pullRequest=59&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=Learnathon-By-Geeky-Solutions_h3cker&pullRequest=59&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=Learnathon-By-Geeky-Solutions_h3cker&pullRequest=59)


author_association: NONE