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

Commit 849c411

Browse files
committed
Merge branch 'main' into Ajay/remove-references-to-old-plan-representations
2 parents a2a853a + 4ed721d commit 849c411

Some content is hidden

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

44 files changed

+347
-1154
lines changed

codecov/settings_base.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@
443443
"profiling": "shared.django_apps.profiling.migrations",
444444
"reports": "shared.django_apps.reports.migrations",
445445
"staticanalysis": "shared.django_apps.staticanalysis.migrations",
446+
"timeseries": "shared.django_apps.timeseries.migrations",
446447
}
447448

448449
# to aid in debugging, print out this info on startup. If no license, prints nothing

codecov_auth/authentication/repo_auth.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from django.utils import timezone
1010
from jwt import PyJWTError
1111
from rest_framework import authentication, exceptions, serializers
12-
from rest_framework.exceptions import NotAuthenticated
12+
from rest_framework.exceptions import NotAuthenticated, ValidationError
1313
from rest_framework.response import Response
1414
from rest_framework.views import exception_handler
1515
from shared.django_apps.codecov_auth.models import Owner
@@ -200,7 +200,7 @@ def authenticate(
200200
if not using_global_token:
201201
return None # continue to next auth class
202202

203-
service = global_tokens[token]
203+
service = global_tokens.get(token, "")
204204
upload_info = get_upload_info_from_request_path(request)
205205
if upload_info is None:
206206
return None # continue to next auth class
@@ -257,7 +257,7 @@ def authenticate_credentials(
257257

258258
try:
259259
repository = get_repo_with_github_actions_oidc_token(token)
260-
except (ObjectDoesNotExist, PyJWTError):
260+
except (ObjectDoesNotExist, PyJWTError, ValidationError):
261261
return None # continue to next auth class
262262

263263
log.info(

core/admin.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from codecov.admin import AdminMixin
88
from codecov_auth.models import RepositoryToken
99
from core.models import Pull, Repository
10+
from services.task.task import TaskService
1011

1112

1213
class RepositoryTokenInline(admin.TabularInline):
@@ -90,12 +91,19 @@ class RepositoryAdmin(AdminMixin, admin.ModelAdmin):
9091
"webhook_secret",
9192
)
9293

93-
def has_delete_permission(self, request, obj=None):
94-
return False
95-
9694
def has_add_permission(self, _, obj=None):
9795
return False
9896

97+
def has_delete_permission(self, request, obj=None):
98+
return bool(request.user and request.user.is_superuser)
99+
100+
def delete_queryset(self, request, queryset) -> None:
101+
for repo in queryset:
102+
TaskService().flush_repo(repository_id=repo.repoid)
103+
104+
def delete_model(self, request, obj) -> None:
105+
TaskService().flush_repo(repository_id=obj.repoid)
106+
99107

100108
@admin.register(Pull)
101109
class PullsAdmin(AdminMixin, admin.ModelAdmin):

core/apps.py

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

33
from django.apps import AppConfig
4-
from django.core.management import call_command
54
from shared.helpers.cache import RedisBackend
65

76
from services.redis_configuration import get_redis_connection
@@ -17,24 +16,6 @@ class CoreConfig(AppConfig):
1716
def ready(self):
1817
import core.signals # noqa: F401
1918

20-
if RUN_ENV == "DEV":
21-
try:
22-
# Call your management command here
23-
call_command(
24-
"insert_data_to_db_from_csv",
25-
"core/management/commands/codecovTiers-Jan25.csv",
26-
"--model",
27-
"tiers",
28-
)
29-
call_command(
30-
"insert_data_to_db_from_csv",
31-
"core/management/commands/codecovPlans-Jan25.csv",
32-
"--model",
33-
"plans",
34-
)
35-
except Exception as e:
36-
logger.error(f"Failed to run startup command: {e}")
37-
3819
if RUN_ENV not in ["DEV", "TESTING"]:
3920
cache_backend = RedisBackend(get_redis_connection())
4021
cache.configure(cache_backend)

core/management/commands/codecovPlans-Jan25.csv

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
10,2025-01-16 04:40:55.162 -0800,2025-01-24 11:33:46.043 -0800,0,"{""Configurable # of users"",""Unlimited public repositories"",""Unlimited private repositories""}",,true,Developer,,,false,users-trial,6,
33
9,2025-01-16 04:39:59.759 -0800,2025-01-24 11:34:10.038 -0800,10,"{""Configurable # of users"",""Unlimited public repositories"",""Unlimited private repositories"",""Priority Support""}",annually,true,Enterprise Cloud,,,true,users-enterprisey,4,price_1LmjzwGlVGuVgOrkIwlM46EU
44
8,2025-01-16 04:39:15.877 -0800,2025-01-24 11:34:31.904 -0800,12,"{""Configurable # of users"",""Unlimited public repositories"",""Unlimited private repositories"",""Priority Support""}",monthly,true,Enterprise Cloud,,,true,users-enterprisem,4,price_1LmjypGlVGuVgOrkzKtNqhwW
5-
7,2025-01-16 04:38:12.544 -0800,2025-01-24 11:34:53.935 -0800,4,"{""Up to 10 users"",""Unlimited repositories"",""2500 private repo uploads"",""Patch coverage analysis""}",annually,true,Team,10,2500,true,users-teamy,2,price_1NrlXiGlVGuVgOrkgMTw5yno
6-
6,2025-01-16 04:37:08.918 -0800,2025-01-24 11:35:15.346 -0800,5,"{""Up to 10 users"",""Unlimited repositories"",""2500 private repo uploads"",""Patch coverage analysis""}",monthly,true,Team,10,2500,true,users-teamm,2,price_1NqPKdGlVGuVgOrkm9OFvtz8
7-
5,2025-01-16 04:35:34.152 -0800,2025-01-24 11:35:42.724 -0800,10,"{""Includes 5 seats"",""$10 per additional seat"",""Unlimited public repositories"",""Unlimited private repositories"",""Priority Support""}",annually,true,Sentry Pro,5,,true,users-sentryy,5,price_1MlYAYGlVGuVgOrke9SdbBUn
8-
4,2025-01-16 04:34:33.867 -0800,2025-01-24 11:35:48.218 -0800,12,"{""Includes 5 seats"",""$10 per additional seat"",""Unlimited public repositories"",""Unlimited private repositories"",""Priority Support""}",monthly,true,Sentry Pro,5,,true,users-sentrym,5,price_1MlY9yGlVGuVgOrkHluurBtJ
9-
3,2025-01-16 04:32:44.655 -0800,2025-01-24 11:36:09.660 -0800,10,"{""Configurable # of users"",""Unlimited public repositories"",""Unlimited private repositories"",""Priority Support""}",annually,true,Pro,,,true,users-pr-inappy,3,price_1Gv2COGlVGuVgOrkuOYVLIj7
10-
2,2025-01-16 04:30:42.897 -0800,2025-01-24 11:36:14.651 -0800,12,"{""Configurable # of users"",""Unlimited public repositories"",""Unlimited private repositories"",""Priority Support""}",monthly,true,Pro,,,true,users-pr-inappm,3,price_1Gv2B8GlVGuVgOrkFnLunCgc
5+
7,2025-01-16 04:38:12.544 -0800,2025-01-24 11:34:53.935 -0800,4,"{""Up to 10 users"",""Unlimited repositories"",""2500 private repo uploads"",""Patch coverage analysis""}",annually,true,Team,10,2500,true,users-teamy,2,price_1OCM2cGlVGuVgOrkMWUFjPFz
6+
6,2025-01-16 04:37:08.918 -0800,2025-01-24 11:35:15.346 -0800,5,"{""Up to 10 users"",""Unlimited repositories"",""2500 private repo uploads"",""Patch coverage analysis""}",monthly,true,Team,10,2500,true,users-teamm,2,price_1OCM0gGlVGuVgOrkWDYEBtSL
7+
5,2025-01-16 04:35:34.152 -0800,2025-01-24 11:35:42.724 -0800,10,"{""Includes 5 seats"",""$10 per additional seat"",""Unlimited public repositories"",""Unlimited private repositories"",""Priority Support""}",annually,true,Sentry Pro,5,,true,users-sentryy,5,price_1Mj1mMGlVGuVgOrkC0ORc6iW
8+
4,2025-01-16 04:34:33.867 -0800,2025-01-24 11:35:48.218 -0800,12,"{""Includes 5 seats"",""$10 per additional seat"",""Unlimited public repositories"",""Unlimited private repositories"",""Priority Support""}",monthly,true,Sentry Pro,5,,true,users-sentrym,5,price_1Mj1kYGlVGuVgOrk7jucaZAa
9+
3,2025-01-16 04:32:44.655 -0800,2025-01-24 11:36:09.660 -0800,10,"{""Configurable # of users"",""Unlimited public repositories"",""Unlimited private repositories"",""Priority Support""}",annually,true,Pro,,,true,users-pr-inappy,3,plan_H6P16wij3lUuxg
10+
2,2025-01-16 04:30:42.897 -0800,2025-01-24 11:36:14.651 -0800,12,"{""Configurable # of users"",""Unlimited public repositories"",""Unlimited private repositories"",""Priority Support""}",monthly,true,Pro,,,true,users-pr-inappm,3,plan_H6P3KZXwmAbqPS
1111
13,2025-01-23 14:25:04.793 -0800,2025-01-23 14:25:04.793 -0800,12,"{""Configurable # of users"",""Unlimited public repositories"",""Unlimited private repositories""}",,true,Github Marketplace,,,false,users,3,
1212
12,2025-01-16 04:44:51.064 -0800,2025-01-24 11:33:14.405 -0800,0,"{""Up to 1 user"",""Unlimited public repositories"",""Unlimited private repositories""}",,true,Developer,1,250,false,users-developer,2,
1313
11,2025-01-16 04:44:01.249 -0800,2025-01-24 11:33:28.532 -0800,0,"{""Up to 1 user"",""Unlimited public repositories"",""Unlimited private repositories""}",,true,Developer,1,250,false,users-basic,1,

core/management/commands/insert_data_to_db_from_csv.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,15 @@ def handle(self, *args, **kwargs):
5151
)
5252
continue
5353

54-
Model.objects.create(**model_data)
55-
self.stdout.write(self.style.SUCCESS(f"Inserted row: {row}"))
54+
try:
55+
Model.objects.update_or_create(
56+
defaults=model_data,
57+
id=row.get("id"),
58+
)
59+
self.stdout.write(self.style.SUCCESS(f"Inserted row: {row}"))
60+
except Exception as e:
61+
self.stdout.write(self.style.ERROR(f"Error inserting row: {e}"))
62+
continue
5663

5764
self.stdout.write(
5865
self.style.SUCCESS(

dev.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# starts the development server using gunicorn
44
# NEVER run production with the --reload option command
5-
echo "Starting gunicorn in dev mode"
5+
echo "API: Starting gunicorn in dev mode"
66

77
_start_gunicorn() {
88
if [ -n "$PROMETHEUS_MULTIPROC_DIR" ]; then
@@ -19,6 +19,8 @@ _start_gunicorn() {
1919
python manage.py migrate
2020
python manage.py migrate --database "timeseries" timeseries
2121
python manage.py pgpartition --yes --skip-delete
22+
python manage.py insert_data_to_db_from_csv core/management/commands/codecovTiers-Jan25.csv --model tiers
23+
python manage.py insert_data_to_db_from_csv core/management/commands/codecovPlans-Jan25.csv --model plans
2224
fi
2325
if [[ "$DEBUGPY" ]]; then
2426
pip install debugpy

graphql_api/tests/test_owner.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
from billing.helpers import mock_all_plans_and_tiers
2727
from codecov.commands.exceptions import (
28-
MissingService,
2928
UnauthorizedGuestAccess,
3029
)
3130
from codecov_auth.models import GithubAppInstallation, OwnerProfile
@@ -708,7 +707,6 @@ def test_owner_query_with_no_service(self):
708707

709708
res = self.gql_request(query, provider="", with_errors=True)
710709

711-
assert res["errors"][0]["message"] == MissingService.message
712710
assert res["data"]["owner"] is None
713711

714712
def test_owner_query_with_private_repos(self):
@@ -1195,3 +1193,19 @@ def test_fetch_available_plans_is_enterprise_plan(self):
11951193
]
11961194
}
11971195
}
1196+
1197+
def test_fetch_owner_with_no_service(self):
1198+
current_org = OwnerFactory(
1199+
username="random-plan-user",
1200+
service="github",
1201+
plan=PlanName.BASIC_PLAN_NAME.value,
1202+
)
1203+
1204+
query = """{
1205+
owner(username: "%s") {
1206+
username
1207+
}
1208+
}
1209+
""" % (current_org.username)
1210+
data = self.gql_request(query, owner=current_org, provider="", with_errors=True)
1211+
assert data == {"data": {"owner": None}}

graphql_api/tests/test_views.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,3 +309,23 @@ async def test_required_variable_missing(self):
309309
data = await self.do_query(schema, query=query, variables={})
310310

311311
assert data == {"detail": "Missing required variables: name", "status": 400}
312+
313+
async def test_empty_request_body(self):
314+
schema = generate_schema_with_required_variables()
315+
316+
request = RequestFactory().post(
317+
"/graphql/gh", "", content_type="application/json"
318+
)
319+
match = ResolverMatch(func=lambda: None, args=(), kwargs={"service": "github"})
320+
request.resolver_match = match
321+
request.user = None
322+
request.current_owner = None
323+
324+
view = AsyncGraphqlView.as_view(schema=schema)
325+
response = await view(request, service="gh")
326+
327+
assert response.status_code == 400
328+
assert json.loads(response.content) == {
329+
"status": 400,
330+
"detail": "Invalid JSON response received.",
331+
}

graphql_api/types/errors/errors.graphql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,7 @@ type ProviderError implements ResolverError {
3737
type OwnerNotActivatedError implements ResolverError {
3838
message: String!
3939
}
40+
41+
type MissingService implements ResolverError {
42+
message: String!
43+
}

0 commit comments

Comments
 (0)