Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 218 additions & 0 deletions apps/api/docs/django-5.2-migration-plan.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Generated by Django 5.2.15 on 2026-06-26 15:33

from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('db', '0121_alter_estimate_type'),
]

operations = [
migrations.AlterField(
model_name='draftissue',
name='assignees',
field=models.ManyToManyField(blank=True, related_name='draft_assignee', through='db.DraftIssueAssignee', through_fields=('draft_issue', 'assignee'), to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='issue',
name='assignees',
field=models.ManyToManyField(blank=True, related_name='assignee', through='db.IssueAssignee', through_fields=('issue', 'assignee'), to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='module',
name='members',
field=models.ManyToManyField(blank=True, related_name='module_members', through='db.ModuleMember', through_fields=('module', 'member'), to=settings.AUTH_USER_MODEL),
),
]
16 changes: 16 additions & 0 deletions apps/api/plane/tests/contract/app/test_authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@
from plane.license.models import Instance


@pytest.fixture(autouse=True)
def _reset_auth_throttle_cache():
"""Clear the shared cache around every test in this module.

The auth endpoints apply a per-IP throttle (AuthenticationThrottle) whose
request history lives in the Django cache. Because the test session reuses a
single cache, that count leaks across tests and trips RATE_LIMIT_EXCEEDED in
classes that don't reset it. This mirrors the per-class ``_clear_state``
fixtures already used by the throttle / verify-attempt classes, applied
module-wide so every auth test starts from a clean throttle state.
"""
cache.clear()
yield
cache.clear()
Comment on lines +23 to +36

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Cache backend used by tests =="
fd -t f 'test.*settings.*|settings.*test.*|settings.py|common.py' apps/api | xargs -r rg -n -C2 'CACHES|django_redis|RedisCache|LocMemCache'

echo
echo "== Whole-cache clears in tests =="
rg -n -C2 '\bcache\.clear\s*\(' apps/api/plane/tests

echo
echo "== Authentication throttle definitions / keying =="
rg -n -C3 'AuthenticationThrottle|RATE_LIMIT_EXCEEDED|throttle' apps/api/plane

Repository: makeplane/plane

Length of output: 32504


Avoid flushing the entire shared cache; scope cleanup to authentication throttle keys.

The cache.clear() calls on lines 34 and 36 purge the entire Redis cache alias. In a shared backend setup (confirmed in apps/api/plane/settings/common.py) used with pytest-xdist, this wipes unrelated cached state (sessions, feature flags, etc.) and introduces cross-test flakiness.

Replace cache.clear() with targeted deletion of keys matching the DRF throttle pattern throttle_authentication_*, or configure a dedicated cache alias for test isolation.

Example targeted cleanup approach
from django.core.cache import cache
from django_redis import get_redis_connection

# DRF key pattern: throttle_<scope>_<identity>
# For AuthenticationThrottle (scope="authentication"), keys match "throttle_authentication_*"
THROTTLE_PREFIX = "throttle_authentication_"

def _clear_auth_throttle_keys():
    """Delete only auth throttle keys to avoid wiping unrelated cache data."""
    redis_client = get_redis_connection("default")
    # Scan and delete matching keys
    keys = list(redis_client.keys(f"{THROTTLE_PREFIX}*"))
    if keys:
        redis_client.delete(*keys)

`@pytest.fixture`(autouse=True)
def _reset_auth_throttle_cache():
    _clear_auth_throttle_keys()
    yield
    _clear_auth_throttle_keys()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/plane/tests/contract/app/test_authentication.py` around lines 23 -
36, The module-wide auth cache fixture is wiping the entire shared Redis cache,
which can affect unrelated state across tests. Update the
`_reset_auth_throttle_cache` fixture in `test_authentication.py` to remove only
`AuthenticationThrottle` entries, using targeted deletion of
`throttle_authentication_*` keys (for example via a helper like
`_clear_auth_throttle_keys`) instead of calling `cache.clear()`. Keep the
cleanup before and after the test via the fixture, but scope it to the throttle
cache keys only.



@pytest.fixture
def setup_instance(db):
"""Create and configure an instance for authentication tests"""
Expand Down
3 changes: 2 additions & 1 deletion apps/api/plane/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

"""plane URL Configuration"""

from django.apps import apps
from django.conf import settings
from django.urls import include, path, re_path
from drf_spectacular.views import (
Expand Down Expand Up @@ -38,7 +39,7 @@
),
]

if settings.DEBUG:
if settings.DEBUG and apps.is_installed("debug_toolbar"):
try:
import debug_toolbar

Expand Down
34 changes: 17 additions & 17 deletions apps/api/requirements/base.txt
Original file line number Diff line number Diff line change
@@ -1,45 +1,45 @@
# base requirements

# django
Django==4.2.30
Django==5.2.15
# rest framework
djangorestframework==3.15.2
djangorestframework==3.17.1
# postgres
psycopg==3.3.0
psycopg-binary==3.3.0
psycopg-c==3.3.0
dj-database-url==2.1.0
psycopg==3.3.4
psycopg-binary==3.3.4
psycopg-c==3.3.4
dj-database-url==3.0.1
# redis
redis==5.0.4
django-redis==5.4.0
django-redis==7.0.0
# cors
django-cors-headers==4.3.1
django-cors-headers==4.9.0
# celery
celery==5.4.0
django_celery_beat==2.6.0
django-celery-results==2.5.1
celery==5.5.3
django_celery_beat==2.9.0
django-celery-results==2.6.0
# file serve
whitenoise==6.11.0
whitenoise==6.12.0
# fake data
faker==25.0.0
# filters
django-filter==24.2
django-filter==25.2
# json model
jsonmodels==2.7.0
# storage
django-storages==1.14.2
django-storages==1.14.6
# user management
django-crum==0.7.9
# web server
uvicorn==0.29.0
# sockets
channels==4.1.0
channels==4.3.2
# ai
openai==1.63.2
# slack
slack-sdk==3.27.1
# apm
scout-apm==3.1.0
scout-apm==3.5.3
# xlsx generation
openpyxl==3.1.2
# logging
Expand Down Expand Up @@ -72,6 +72,6 @@ opentelemetry-instrumentation-django==0.49b1
opentelemetry-exporter-otlp==1.28.1
opentelemetry-exporter-otlp-proto-grpc==1.28.1
# OpenAPI Specification
drf-spectacular==0.28.0
drf-spectacular==0.29.0
# html sanitizer
nh3==0.2.18
2 changes: 1 addition & 1 deletion apps/api/requirements/local.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
-r base.txt
# debug toolbar
django-debug-toolbar==4.3.0
django-debug-toolbar==6.0.0
# formatter
ruff==0.9.7
2 changes: 1 addition & 1 deletion apps/api/requirements/test.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-r base.txt
# test framework
pytest==9.0.3
pytest-django==4.5.2
pytest-django==4.12.0
pytest-cov==4.1.0
pytest-xdist==3.3.1
pytest-mock==3.11.1
Expand Down
Loading