Skip to content

Commit

Permalink
Merge branch 'main' into rvinnakota/add-ip-address-sentry
Browse files Browse the repository at this point in the history
  • Loading branch information
rohitvinnakota-codecov authored Sep 11, 2024
2 parents 14e4b69 + f6ed141 commit 263a518
Show file tree
Hide file tree
Showing 484 changed files with 12,070 additions and 5,413 deletions.
16 changes: 8 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@ permissions:
jobs:
lint:
name: Run Lint
uses: codecov/gha-workflows/.github/workflows/lint.yml@v1.2.21
uses: codecov/gha-workflows/.github/workflows/lint.yml@v1.2.23

build:
name: Build API
uses: codecov/gha-workflows/.github/workflows/build-app.yml@v1.2.21
uses: codecov/gha-workflows/.github/workflows/build-app.yml@v1.2.23
secrets: inherit
with:
repo: ${{ vars.CODECOV_IMAGE_V2 || 'codecov/self-hosted-api' }}

codecovstartup:
name: Codecov Startup
needs: build
uses: codecov/gha-workflows/.github/workflows/codecov-startup.yml@v1.2.21
uses: codecov/gha-workflows/.github/workflows/codecov-startup.yml@v1.2.23
secrets: inherit

# ats:
Expand All @@ -47,15 +47,15 @@ jobs:
test:
name: Test
needs: [build]
uses: codecov/gha-workflows/.github/workflows/run-tests.yml@v1.2.21
uses: codecov/gha-workflows/.github/workflows/run-tests.yml@v1.2.23
secrets: inherit
with:
repo: ${{ vars.CODECOV_IMAGE_V2 || 'codecov/self-hosted-api' }}

build-self-hosted:
name: Build Self Hosted API
needs: [build, test]
uses: codecov/gha-workflows/.github/workflows/self-hosted.yml@v1.2.21
uses: codecov/gha-workflows/.github/workflows/self-hosted.yml@v1.2.23
secrets: inherit
with:
repo: ${{ vars.CODECOV_IMAGE_V2 || 'codecov/self-hosted-api' }}
Expand All @@ -64,7 +64,7 @@ jobs:
name: Push Staging Image
needs: [build, test]
if: ${{ github.event_name == 'push' && github.event.ref == 'refs/heads/staging' && github.repository_owner == 'codecov' }}
uses: codecov/gha-workflows/.github/workflows/push-env.yml@v1.2.21
uses: codecov/gha-workflows/.github/workflows/push-env.yml@v1.2.23
secrets: inherit
with:
environment: staging
Expand All @@ -74,7 +74,7 @@ jobs:
name: Push Production Image
needs: [build, test]
if: ${{ github.event_name == 'push' && github.event.ref == 'refs/heads/main' && github.repository_owner == 'codecov' }}
uses: codecov/gha-workflows/.github/workflows/push-env.yml@v1.2.21
uses: codecov/gha-workflows/.github/workflows/push-env.yml@v1.2.23
secrets: inherit
with:
environment: production
Expand All @@ -85,7 +85,7 @@ jobs:
needs: [build-self-hosted, test]
secrets: inherit
if: ${{ github.event_name == 'push' && github.event.ref == 'refs/heads/main' && github.repository_owner == 'codecov' }}
uses: codecov/gha-workflows/.github/workflows/self-hosted.yml@v1.2.21
uses: codecov/gha-workflows/.github/workflows/self-hosted.yml@v1.2.23
with:
push_rolling: true
repo: ${{ vars.CODECOV_IMAGE_V2 || 'codecov/self-hosted-api' }}
14 changes: 14 additions & 0 deletions .github/workflows/pr_detect_shared_changes.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Detect dep version changes

on:
pull_request:

permissions:
pull-requests: "write"

jobs:
shared-change-checker:
name: See if shared changed
uses: codecov/gha-workflows/.github/workflows/diff-dep.yml@main
with:
dep: 'shared'
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
24.6.1
24.9.1
9 changes: 3 additions & 6 deletions api/internal/branch/views.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
from django.db.models import F, OuterRef, Subquery
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters, mixins, viewsets
from django.db.models import OuterRef, Subquery
from rest_framework import mixins

from api.shared.branch.mixins import BranchViewSetMixin
from api.shared.mixins import RepoPropertyMixin
from api.shared.permissions import RepositoryArtifactPermissions
from core.models import Branch, Commit
from core.models import Commit

from .serializers import BranchSerializer

Expand Down
4 changes: 2 additions & 2 deletions api/internal/chart/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
from cerberus import Validator
from dateutil import parser
from django.db import connection
from django.db.models import Case, F, FloatField, Value, When
from django.db.models import Case, FloatField, Value, When
from django.db.models.fields.json import KeyTextTransform
from django.db.models.functions import Cast, Trunc
from django.utils import timezone
from django.utils.functional import cached_property
from rest_framework.exceptions import ValidationError

from codecov_auth.models import Owner
from core.models import Commit, Repository
from core.models import Repository


class ChartParamValidator(Validator):
Expand Down
2 changes: 1 addition & 1 deletion api/internal/chart/urls.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from django.urls import path, re_path
from django.urls import re_path

from .views import OrganizationChartHandler, RepositoryChartHandler

Expand Down
9 changes: 7 additions & 2 deletions api/internal/chart/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from api.shared.mixins import RepositoriesMixin
from api.shared.permissions import ChartPermissions
from core.models import Commit
from utils import round_decimals_down

from .filters import apply_default_filters, apply_simple_filters
from .helpers import (
Expand Down Expand Up @@ -102,7 +103,9 @@ def post(self, request, *args, **kwargs):
complexity = [
{
"date": commit.timestamp,
"complexity_ratio": round(commit.complexity_ratio * 100, 2),
"complexity_ratio": round_decimals_down(
commit.complexity_ratio * 100, 2
),
"commitid": commit.commitid,
}
for commit in commits
Expand Down Expand Up @@ -136,7 +139,9 @@ def post(self, request, *args, **kwargs):
complexity = [
{
"date": commit.truncated_date,
"complexity_ratio": round(commit.complexity_ratio * 100, 2),
"complexity_ratio": round_decimals_down(
commit.complexity_ratio * 100, 2
),
"commitid": commit.commitid,
}
for commit in complexity_grouped_queryset
Expand Down
8 changes: 2 additions & 6 deletions api/internal/enterprise_urls.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
from django.urls import include, path

from api.internal.self_hosted.views import SettingsViewSet, UserViewSet
from utils.routers import OptionalTrailingSlashRouter, RetrieveUpdateDestroyRouter
from api.internal.self_hosted.views import UserViewSet
from utils.routers import OptionalTrailingSlashRouter

self_hosted_router = OptionalTrailingSlashRouter()
self_hosted_router.register(r"users", UserViewSet, basename="selfhosted-users")

settings_router = RetrieveUpdateDestroyRouter()
settings_router.register(r"settings", SettingsViewSet, basename="selfhosted-settings")

urlpatterns = [
path("license/", include("api.internal.license.urls")),
path("", include(settings_router.urls)),
path("", include(self_hosted_router.urls)),
]
51 changes: 43 additions & 8 deletions api/internal/owner/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,11 @@ def validate_value(self, value):
return value

def validate(self, plan):
owner = self.context["view"].owner
current_org = self.context["view"].owner
if current_org.account:
raise serializers.ValidationError(
detail="You cannot update your plan manually, for help or changes to plan, connect with sales@codecov.io"
)

# Validate quantity here because we need access to whole plan object
if plan["value"] in PAID_PLANS:
Expand All @@ -156,16 +160,19 @@ def validate(self, plan):
"Quantity for paid plan must be greater than 1"
)

plan_service = PlanService(current_org=owner)
plan_service = PlanService(current_org=current_org)
is_org_trialing = plan_service.is_org_trialing

if plan["quantity"] < owner.activated_user_count and not is_org_trialing:
if (
plan["quantity"] < current_org.activated_user_count
and not is_org_trialing
):
raise serializers.ValidationError(
"Quantity cannot be lower than currently activated user count"
)
if (
plan["quantity"] == owner.plan_user_count
and plan["value"] == owner.plan
plan["quantity"] == current_org.plan_user_count
and plan["value"] == current_org.plan
and not is_org_trialing
):
raise serializers.ValidationError(
Expand All @@ -190,6 +197,9 @@ class SubscriptionDetailSerializer(serializers.Serializer):
current_period_end = serializers.IntegerField()
customer = StripeCustomerSerializer()
collection_method = serializers.CharField()
tax_ids = serializers.ListField(
source="customer.tax_ids.data", read_only=True, allow_null=True
)
trial_end = serializers.IntegerField()


Expand Down Expand Up @@ -249,6 +259,10 @@ class AccountDetailsSerializer(serializers.ModelSerializer):
root_organization = RootOrganizationSerializer()
schedule_detail = serializers.SerializerMethodField()
apply_cancellation_discount = serializers.BooleanField(write_only=True)
activated_student_count = serializers.SerializerMethodField()
activated_user_count = serializers.SerializerMethodField()
delinquent = serializers.SerializerMethodField()
uses_invoice = serializers.SerializerMethodField()

class Meta:
model = Owner
Expand All @@ -258,21 +272,22 @@ class Meta:
fields = read_only_fields + (
"activated_student_count",
"activated_user_count",
"apply_cancellation_discount",
"checkout_session_id",
"delinquent",
"email",
"inactive_user_count",
"name",
"nb_active_private_repos",
"plan",
"plan_auto_activate",
"plan_provider",
"uses_invoice",
"plan",
"repo_total_credits",
"root_organization",
"schedule_detail",
"student_count",
"subscription_detail",
"apply_cancellation_discount",
"uses_invoice",
)

def _get_billing(self):
Expand All @@ -292,6 +307,26 @@ def get_schedule_detail(self, owner):
def get_checkout_session_id(self, _):
return self.context.get("checkout_session_id")

def get_activated_student_count(self, owner):
if owner.account:
return owner.account.activated_student_count
return owner.activated_student_count

def get_activated_user_count(self, owner):
if owner.account:
return owner.account.activated_user_count
return owner.activated_user_count

def get_delinquent(self, owner):
if owner.account:
return owner.account.is_delinquent
return owner.delinquent

def get_uses_invoice(self, owner):
if owner.account:
return owner.account.invoice_billing.filter(is_active=True).exists()
return owner.uses_invoice

def update(self, instance, validated_data):
if "pretty_plan" in validated_data:
desired_plan = validated_data.pop("pretty_plan")
Expand Down
53 changes: 24 additions & 29 deletions api/internal/owner/views.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import logging
from dataclasses import asdict

from django.db.models import F
from django_filters import rest_framework as django_filters
from rest_framework import filters, mixins, status, viewsets
from rest_framework.decorators import action
from rest_framework.exceptions import NotFound, PermissionDenied, ValidationError
from rest_framework.exceptions import PermissionDenied, ValidationError
from rest_framework.response import Response
from shared.django_apps.codecov_auth.models import Owner

from api.shared.mixins import OwnerPropertyMixin
from api.shared.owner.mixins import OwnerViewSetMixin, UserViewSetMixin
Expand All @@ -19,7 +19,6 @@
from .serializers import (
AccountDetailsSerializer,
OwnerSerializer,
StripeInvoiceSerializer,
UserSerializer,
)

Expand All @@ -30,31 +29,6 @@ class OwnerViewSet(OwnerViewSetMixin, mixins.RetrieveModelMixin):
serializer_class = OwnerSerializer


class InvoiceViewSet(
viewsets.GenericViewSet,
mixins.ListModelMixin,
mixins.RetrieveModelMixin,
OwnerPropertyMixin,
):
serializer_class = StripeInvoiceSerializer
permission_classes = [MemberOfOrgPermissions]
pagination_class = None

def get_queryset(self):
return BillingService(
requesting_user=self.request.current_owner
).list_filtered_invoices(self.owner, 100)

def get_object(self):
invoice_id = self.kwargs.get("pk")
invoice = BillingService(
requesting_user=self.request.current_owner
).get_invoice(self.owner, invoice_id)
if not invoice:
raise NotFound(f"Invoice {invoice_id} does not exist for that account")
return invoice


class AccountDetailsViewSet(
viewsets.GenericViewSet,
mixins.UpdateModelMixin,
Expand Down Expand Up @@ -82,6 +56,14 @@ def destroy(self, request, *args, **kwargs):
return Response(status=status.HTTP_204_NO_CONTENT)

def get_object(self):
if self.owner.account:
# gets the related account and invoice_billing objects from db in 1 query
# otherwise, each reference to owner.account would be an additional query
self.owner = (
Owner.objects.filter(pk=self.owner.ownerid)
.select_related("account__invoice_billing")
.first()
)
return self.owner

@action(detail=False, methods=["patch"])
Expand Down Expand Up @@ -109,12 +91,25 @@ def update_email(self, request, *args, **kwargs):
@action(detail=False, methods=["patch"])
@stripe_safe
def update_billing_address(self, request, *args, **kwargs):
name = request.data.get("name")
if not name:
raise ValidationError(detail="No name sent")
billing_address = request.data.get("billing_address")
if not billing_address:
raise ValidationError(detail="No billing_address sent")
owner = self.get_object()

formatted_address = {
"line1": billing_address["line_1"],
"line2": billing_address["line_2"],
"city": billing_address["city"],
"state": billing_address["state"],
"postal_code": billing_address["postal_code"],
"country": billing_address["country"],
}

billing = BillingService(requesting_user=request.current_owner)
billing.update_billing_address(owner, billing_address)
billing.update_billing_address(owner, name, billing_address=formatted_address)
return Response(self.get_serializer(owner).data)


Expand Down
Loading

0 comments on commit 263a518

Please sign in to comment.