Skip to content
This repository was archived by the owner on Jun 13, 2025. It is now read-only.

Commit ad264ab

Browse files
authored
Merge branch 'main' into feb_05_fix_upload_serializer
2 parents 075a377 + a12b039 commit ad264ab

File tree

90 files changed

+1238
-1940
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+1238
-1940
lines changed

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
25.2.3
1+
25.2.7

api/internal/owner/serializers.py

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from typing import Any, Dict
44

55
from dateutil.relativedelta import relativedelta
6-
from django.conf import settings
76
from rest_framework import serializers
87
from rest_framework.exceptions import PermissionDenied
98
from shared.plan.constants import (
@@ -132,7 +131,7 @@ def validate_value(self, value: str) -> str:
132131

133132
plan_service = PlanService(current_org=current_org)
134133
plan_values = [
135-
plan["value"] for plan in plan_service.available_plans(current_owner)
134+
plan.name for plan in plan_service.available_plans(current_owner)
136135
]
137136
if value not in plan_values:
138137
raise serializers.ValidationError(
@@ -217,11 +216,7 @@ class StripeScheduledPhaseSerializer(serializers.Serializer):
217216

218217
def get_plan(self, phase: Dict[str, Any]) -> str:
219218
plan_id = phase["items"][0]["plan"]
220-
stripe_plan_dict = settings.STRIPE_PLAN_IDS
221-
plan_name = list(stripe_plan_dict.keys())[
222-
list(stripe_plan_dict.values()).index(plan_id)
223-
]
224-
marketing_plan_name = Plan.objects.get(name=plan_name).marketing_name
219+
marketing_plan_name = Plan.objects.get(stripe_id=plan_id).marketing_name
225220
return marketing_plan_name
226221

227222
def get_quantity(self, phase: Dict[str, Any]) -> int:
@@ -344,11 +339,13 @@ def update(self, instance: Owner, validated_data: Dict[str, Any]) -> object:
344339
instance, desired_plan
345340
)
346341

347-
sentry_plans = Plan.objects.filter(
348-
tier__tier_name=TierName.SENTRY.value, is_active=True
349-
).values_list("name", flat=True)
342+
plan = (
343+
Plan.objects.select_related("tier")
344+
.filter(name=desired_plan["value"])
345+
.first()
346+
)
350347

351-
if desired_plan["value"] in sentry_plans:
348+
if plan and plan.tier.tier_name == TierName.SENTRY.value:
352349
current_owner = self.context["view"].request.current_owner
353350
send_sentry_webhook(current_owner, instance)
354351

api/internal/tests/views/test_account_viewset.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ def test_retrieve_account_gets_account_fields_when_there_are_scheduled_details(
234234
schedule_params = {
235235
"id": 123,
236236
"start_date": 123689126736,
237-
"stripe_plan_id": "plan_H6P3KZXwmAbqPS",
237+
"stripe_plan_id": "plan_pro_yearly",
238238
"quantity": 6,
239239
}
240240
phases = [
@@ -330,7 +330,7 @@ def test_retrieve_account_returns_last_phase_when_more_than_one_scheduled_phases
330330
schedule_params = {
331331
"id": 123,
332332
"start_date": 123689126736,
333-
"stripe_plan_id": "plan_H6P3KZXwmAbqPS",
333+
"stripe_plan_id": "plan_pro_yearly",
334334
"quantity": 6,
335335
}
336336
phases = [

api/internal/tests/views/test_user_viewset.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
PullFactory,
1111
RepositoryFactory,
1212
)
13-
from shared.plan.constants import PlanName, TierName
13+
from shared.plan.constants import DEFAULT_FREE_PLAN, TierName
1414

1515
from core.models import Pull
1616
from utils.test_utils import APIClient
@@ -20,7 +20,7 @@ class UserViewSetTests(APITestCase):
2020
def setUp(self):
2121
non_org_active_user = OwnerFactory()
2222
tier = TierFactory(tier_name=TierName.BASIC.value)
23-
plan = PlanFactory(name=PlanName.BASIC_PLAN_NAME.value, tier=tier)
23+
plan = PlanFactory(name=DEFAULT_FREE_PLAN, tier=tier)
2424
self.current_owner = OwnerFactory(
2525
plan=plan.name,
2626
plan_user_count=5,

api/public/v1/serializers.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,7 @@ class Meta:
1616
"state",
1717
)
1818
fields = read_only_fields + ("user_provided_base_sha",)
19+
20+
21+
class PullIdSerializer(serializers.Serializer):
22+
pullid = serializers.IntegerField()

api/public/v1/tests/views/test_pull_viewset.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,10 @@ def test_post_pull_user_provided_base(self, pulls_sync_mock):
133133
)
134134
self.assertEqual(response.status_code, 405)
135135
assert not pulls_sync_mock.called
136+
137+
def test_get_pull_no_pullid_provided(self):
138+
self.client.credentials(HTTP_AUTHORIZATION="Token " + self.repo.upload_token)
139+
response = self.client.get("/api/github/codecov/testRepoName/pulls/abc")
140+
self.assertEqual(response.status_code, 400)
141+
content = json.loads(response.content.decode())
142+
self.assertEqual(content["pullid"], ["A valid integer is required."])

api/public/v1/views.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import logging
22

3-
from django.db.models import OuterRef, Subquery
3+
from django.db.models import OuterRef, QuerySet, Subquery
44
from django.shortcuts import get_object_or_404
55
from django_filters.rest_framework import DjangoFilterBackend
66
from rest_framework import filters, mixins, viewsets
77

88
from api.shared.mixins import RepoPropertyMixin
99
from codecov_auth.authentication.repo_auth import RepositoryLegacyTokenAuthentication
10-
from core.models import Commit
10+
from core.models import Commit, Pull
1111
from services.task import TaskService
1212

1313
from .permissions import PullUpdatePermission
14-
from .serializers import PullSerializer
14+
from .serializers import PullIdSerializer, PullSerializer
1515

1616
log = logging.getLogger(__name__)
1717

@@ -30,8 +30,11 @@ class PullViewSet(
3030
authentication_classes = [RepositoryLegacyTokenAuthentication]
3131
permission_classes = [PullUpdatePermission]
3232

33-
def get_object(self):
34-
pullid = self.kwargs.get("pk")
33+
def get_object(self) -> Pull:
34+
serializer = PullIdSerializer(data={"pullid": self.kwargs.get("pk")})
35+
serializer.is_valid(raise_exception=True)
36+
pullid = serializer.validated_data["pullid"]
37+
3538
if self.request.method == "PUT":
3639
# Note: We create a new pull if needed to make sure that they can be updated
3740
# with a base before the upload has finished processing.
@@ -41,7 +44,7 @@ def get_object(self):
4144
return obj
4245
return get_object_or_404(self.get_queryset(), pullid=pullid)
4346

44-
def get_queryset(self):
47+
def get_queryset(self) -> QuerySet:
4548
return self.repo.pull_requests.annotate(
4649
ci_passed=Subquery(
4750
Commit.objects.filter(
@@ -50,7 +53,7 @@ def get_queryset(self):
5053
)
5154
)
5255

53-
def perform_update(self, serializer):
56+
def perform_update(self, serializer: PullSerializer) -> Pull:
5457
result = super().perform_update(serializer)
5558
TaskService().pulls_sync(repoid=self.repo.repoid, pullid=self.kwargs.get("pk"))
5659
return result

api/public/v2/compare/serializers.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ class ComparisonSerializer(BaseComparisonSerializer):
1616

1717
def get_files(self, comparison: Comparison) -> List[dict]:
1818
data = []
19-
for filename in comparison.head_report.files:
20-
file = comparison.get_file_comparison(filename, bypass_max_diff=True)
21-
if self._should_include_file(file):
22-
data.append(FileComparisonSerializer(file).data)
19+
if comparison.head_report is not None:
20+
for filename in comparison.head_report.files:
21+
file = comparison.get_file_comparison(filename, bypass_max_diff=True)
22+
if self._should_include_file(file):
23+
data.append(FileComparisonSerializer(file).data)
2324
return data
2425

2526

billing/helpers.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ def get_all_admins_for_owners(owners: QuerySet[Owner]):
2727

2828

2929
def mock_all_plans_and_tiers():
30+
TierFactory(tier_name=TierName.BASIC.value)
31+
3032
trial_tier = TierFactory(tier_name=TierName.TRIAL.value)
3133
PlanFactory(
3234
tier=trial_tier,
@@ -39,18 +41,7 @@ def mock_all_plans_and_tiers():
3941
"Unlimited private repositories",
4042
"Priority Support",
4143
],
42-
)
43-
44-
basic_tier = TierFactory(tier_name=TierName.BASIC.value)
45-
PlanFactory(
46-
name=PlanName.FREE_PLAN_NAME.value,
47-
tier=basic_tier,
48-
marketing_name="Developer",
49-
benefits=[
50-
"Up to 1 user",
51-
"Unlimited public repositories",
52-
"Unlimited private repositories",
53-
],
44+
stripe_id="plan_trial",
5445
)
5546

5647
pro_tier = TierFactory(tier_name=TierName.PRO.value)
@@ -67,6 +58,7 @@ def mock_all_plans_and_tiers():
6758
billing_rate=BillingRate.MONTHLY.value,
6859
base_unit_price=PlanPrice.MONTHLY.value,
6960
paid_plan=True,
61+
stripe_id="plan_pro",
7062
)
7163
PlanFactory(
7264
name=PlanName.CODECOV_PRO_YEARLY.value,
@@ -81,6 +73,7 @@ def mock_all_plans_and_tiers():
8173
billing_rate=BillingRate.ANNUALLY.value,
8274
base_unit_price=PlanPrice.YEARLY.value,
8375
paid_plan=True,
76+
stripe_id="plan_pro_yearly",
8477
)
8578

8679
team_tier = TierFactory(tier_name=TierName.TEAM.value)
@@ -98,6 +91,7 @@ def mock_all_plans_and_tiers():
9891
base_unit_price=PlanPrice.TEAM_MONTHLY.value,
9992
monthly_uploads_limit=2500,
10093
paid_plan=True,
94+
stripe_id="plan_team_monthly",
10195
)
10296
PlanFactory(
10397
name=PlanName.TEAM_YEARLY.value,
@@ -113,6 +107,7 @@ def mock_all_plans_and_tiers():
113107
base_unit_price=PlanPrice.TEAM_YEARLY.value,
114108
monthly_uploads_limit=2500,
115109
paid_plan=True,
110+
stripe_id="plan_team_yearly",
116111
)
117112

118113
sentry_tier = TierFactory(tier_name=TierName.SENTRY.value)
@@ -130,6 +125,7 @@ def mock_all_plans_and_tiers():
130125
"Unlimited private repositories",
131126
"Priority Support",
132127
],
128+
stripe_id="plan_sentry_monthly",
133129
)
134130
PlanFactory(
135131
name=PlanName.SENTRY_YEARLY.value,
@@ -145,6 +141,7 @@ def mock_all_plans_and_tiers():
145141
"Unlimited private repositories",
146142
"Priority Support",
147143
],
144+
stripe_id="plan_sentry_yearly",
148145
)
149146

150147
enterprise_tier = TierFactory(tier_name=TierName.ENTERPRISE.value)
@@ -161,6 +158,7 @@ def mock_all_plans_and_tiers():
161158
"Unlimited private repositories",
162159
"Priority Support",
163160
],
161+
stripe_id="plan_enterprise_cloud_monthly",
164162
)
165163
PlanFactory(
166164
name=PlanName.ENTERPRISE_CLOUD_YEARLY.value,
@@ -175,6 +173,7 @@ def mock_all_plans_and_tiers():
175173
"Unlimited private repositories",
176174
"Priority Support",
177175
],
176+
stripe_id="plan_enterprise_cloud_yearly",
178177
)
179178

180179
PlanFactory(
@@ -190,4 +189,5 @@ def mock_all_plans_and_tiers():
190189
"Unlimited public repositories",
191190
"Unlimited private repositories",
192191
],
192+
stripe_id="plan_default_free",
193193
)

0 commit comments

Comments
 (0)