Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Export plans and tiers to CSV #1127

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

RulaKhaled
Copy link
Contributor

Purpose/Motivation

What is the feature? Why is this being done?
Adding a new generic function that allows you to export data from Django portal and feed it to your local DB.

Links to relevant tickets

codecov/engineering-team#3288

Legal Boilerplate

Look, I get it. The entity doing business as "Sentry" was incorporated in the State of Delaware in 2015 as Functional Software, Inc. In 2022 this entity acquired Codecov and as result Sentry is going to need some rights from me in order to utilize my contributions in this PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Sentry can use, modify, copy, and redistribute my contributions, under Sentry's choice of terms.

@codecov-notifications
Copy link

codecov-notifications bot commented Feb 4, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@codecov-qa
Copy link

codecov-qa bot commented Feb 4, 2025

❌ 53 Tests Failed:

Tests completed Failed Passed Skipped
2737 53 2684 7
View the top 3 failed tests by shortest run time
services/tests/test_billing.py::BillingServiceTests::test_update_plan_to_users_basic_sets_plan_if_no_subscription_id
Stack Traces | 0.013s run time
self = <services.tests.test_billing.BillingServiceTests testMethod=test_update_plan_to_users_basic_sets_plan_if_no_subscription_id>
delete_subscription_mock = <MagicMock name='delete_subscription' id='140689237058544'>
modify_subscription_mock = <MagicMock name='modify_subscription' id='140689237052592'>
create_checkout_session_mock = <MagicMock name='create_checkout_session' id='140689217159392'>
set_default_plan_data = <MagicMock name='set_default_plan_data' id='140689217163328'>

    @patch("shared.plan.service.PlanService.set_default_plan_data")
    @patch("services.tests.test_billing.MockPaymentService.create_checkout_session")
    @patch("services.tests.test_billing.MockPaymentService.modify_subscription")
    @patch("services.tests.test_billing.MockPaymentService.delete_subscription")
    def test_update_plan_to_users_basic_sets_plan_if_no_subscription_id(
        self,
        delete_subscription_mock,
        modify_subscription_mock,
        create_checkout_session_mock,
        set_default_plan_data,
    ):
        owner = OwnerFactory()
>       self.billing_service.update_plan(
            owner, {"value": PlanName.BASIC_PLAN_NAME.value}
        )

services/tests/test_billing.py:2162: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
services/billing.py:929: in update_plan
    plan_service = PlanService(current_org=owner)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.plan.service.PlanService object at 0x7ff4cc38f830>
current_org = <Owner: Owner<github/ashley66>>

    def __init__(self, current_org: Owner):
        """
        Initializes a PlanService object for a specific organization.
    
        Args:
            current_org (Owner): The organization for which the plan service is being initialized.
    
        Raises:
            ValueError: If the organization's plan is unsupported.
        """
        if (
            current_org.service == Service.GITLAB.value
            and current_org.parent_service_id
        ):
            # for GitLab groups and subgroups, use the plan on the root org
            self.current_org = current_org.root_organization
        else:
            self.current_org = current_org
    
        if not Plan.objects.filter(name=self.current_org.plan).exists():
>           raise ValueError("Unsupported plan")
E           ValueError: Unsupported plan

.../local/lib/python3.12.../shared/plan/service.py:54: ValueError
billing/tests/test_helpers.py::HelpersTestCase::test_on_enterprise_plan_on_prem
Stack Traces | 0.017s run time
self = <billing.tests.test_helpers.HelpersTestCase testMethod=test_on_enterprise_plan_on_prem>

    @override_settings(IS_ENTERPRISE=True)
    def test_on_enterprise_plan_on_prem(self):
        owner = OwnerFactory()
>       assert on_enterprise_plan(owner) == True

billing/tests/test_helpers.py:17: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
billing/helpers.py:11: in on_enterprise_plan
    plan = Plan.objects.select_related("tier").get(name=owner.plan)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <QuerySet [<Plan: users-trial>, <Plan: users-free>, <Plan: users-basic>, <Plan: users-pr-inappy>, <Plan: users-pr-inap...lan: users-teamm>, <Plan: users-sentryy>, <Plan: users-sentrym>, <Plan: users-enterprisey>, <Plan: users-enterprisem>]>
args = (), kwargs = {'name': 'users-developer'}, clone = <QuerySet []>
limit = 21, num = 0

    def get(self, *args, **kwargs):
        """
        Perform the query and return a single object matching the given
        keyword arguments.
        """
        if self.query.combinator and (args or kwargs):
            raise NotSupportedError(
                "Calling QuerySet.get(...) with filters after %s() is not "
                "supported." % self.query.combinator
            )
        clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs)
        if self.query.can_filter() and not self.query.distinct_fields:
            clone = clone.order_by()
        limit = None
        if (
            not clone.query.select_for_update
            or connections[clone.db].features.supports_select_for_update_with_limit
        ):
            limit = MAX_GET_RESULTS
            clone.query.set_limits(high=limit)
        num = len(clone)
        if num == 1:
            return clone._result_cache[0]
        if not num:
>           raise self.model.DoesNotExist(
                "%s matching query does not exist." % self.model._meta.object_name
            )
E           shared.django_apps.codecov_auth.models.Plan.DoesNotExist: Plan matching query does not exist.

.../local/lib/python3.12.../db/models/query.py:637: DoesNotExist
services/tests/test_billing.py::StripeServiceTests::test_apply_cancellation_discount_existing_coupon
Stack Traces | 0.017s run time
self = <services.tests.test_billing.StripeServiceTests testMethod=test_apply_cancellation_discount_existing_coupon>
customer_modify_mock = <MagicMock name='modify' id='140689377339744'>
coupon_create_mock = <MagicMock name='create' id='140689377330048'>

    @patch("services.billing.stripe.Coupon.create")
    @patch("services.billing.stripe.Customer.modify")
    def test_apply_cancellation_discount_existing_coupon(
        self, customer_modify_mock, coupon_create_mock
    ):
        owner = OwnerFactory(
            stripe_customer_id="test-customer-id",
            stripe_subscription_id="test-subscription-id",
            stripe_coupon_id="test-coupon-id",
        )
>       self.stripe.apply_cancellation_discount(owner)

services/tests/test_billing.py:1896: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
services/billing.py:27: in catch_and_raise
    return method(*args, **kwargs)
services/billing.py:713: in apply_cancellation_discount
    plan_service = PlanService(current_org=owner)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.plan.service.PlanService object at 0x7ff4cc8d7830>
current_org = <Owner: Owner<github/charlesowens>>

    def __init__(self, current_org: Owner):
        """
        Initializes a PlanService object for a specific organization.
    
        Args:
            current_org (Owner): The organization for which the plan service is being initialized.
    
        Raises:
            ValueError: If the organization's plan is unsupported.
        """
        if (
            current_org.service == Service.GITLAB.value
            and current_org.parent_service_id
        ):
            # for GitLab groups and subgroups, use the plan on the root org
            self.current_org = current_org.root_organization
        else:
            self.current_org = current_org
    
        if not Plan.objects.filter(name=self.current_org.plan).exists():
>           raise ValueError("Unsupported plan")
E           ValueError: Unsupported plan

.../local/lib/python3.12.../shared/plan/service.py:54: ValueError

To view more test analytics, go to the Test Analytics Dashboard
📢 Thoughts on this report? Let us know!

Copy link
Contributor

github-actions bot commented Feb 4, 2025

❌ 53 Tests Failed:

Tests completed Failed Passed Skipped
2744 53 2685 6
View the top 3 failed tests by shortest run time
test_update_plan_to_users_basic_sets_plan_if_no_subscription_id
Stack Traces | 0.013s run time
self = &lt;services.tests.test_billing.BillingServiceTests testMethod=test_update_plan_to_users_basic_sets_plan_if_no_subscription_id&gt;
delete_subscription_mock = &lt;MagicMock name='delete_subscription' id='140689237058544'&gt;
modify_subscription_mock = &lt;MagicMock name='modify_subscription' id='140689237052592'&gt;
create_checkout_session_mock = &lt;MagicMock name='create_checkout_session' id='140689217159392'&gt;
set_default_plan_data = &lt;MagicMock name='set_default_plan_data' id='140689217163328'&gt;

    @patch("shared.plan.service.PlanService.set_default_plan_data")
    @patch("services.tests.test_billing.MockPaymentService.create_checkout_session")
    @patch("services.tests.test_billing.MockPaymentService.modify_subscription")
    @patch("services.tests.test_billing.MockPaymentService.delete_subscription")
    def test_update_plan_to_users_basic_sets_plan_if_no_subscription_id(
        self,
        delete_subscription_mock,
        modify_subscription_mock,
        create_checkout_session_mock,
        set_default_plan_data,
    ):
        owner = OwnerFactory()
&gt;       self.billing_service.update_plan(
            owner, {"value": PlanName.BASIC_PLAN_NAME.value}
        )

services/tests/test_billing.py:2162: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
services/billing.py:929: in update_plan
    plan_service = PlanService(current_org=owner)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = &lt;shared.plan.service.PlanService object at 0x7ff4cc38f830&gt;
current_org = &lt;Owner: Owner&lt;github/ashley66&gt;&gt;

    def __init__(self, current_org: Owner):
        """
        Initializes a PlanService object for a specific organization.
    
        Args:
            current_org (Owner): The organization for which the plan service is being initialized.
    
        Raises:
            ValueError: If the organization's plan is unsupported.
        """
        if (
            current_org.service == Service.GITLAB.value
            and current_org.parent_service_id
        ):
            # for GitLab groups and subgroups, use the plan on the root org
            self.current_org = current_org.root_organization
        else:
            self.current_org = current_org
    
        if not Plan.objects.filter(name=self.current_org.plan).exists():
&gt;           raise ValueError("Unsupported plan")
E           ValueError: Unsupported plan

/usr/local/lib/python3.12/site-packages/shared/plan/service.py:54: ValueError
test_on_enterprise_plan_on_prem
Stack Traces | 0.017s run time
self = &lt;billing.tests.test_helpers.HelpersTestCase testMethod=test_on_enterprise_plan_on_prem&gt;

    @override_settings(IS_ENTERPRISE=True)
    def test_on_enterprise_plan_on_prem(self):
        owner = OwnerFactory()
&gt;       assert on_enterprise_plan(owner) == True

billing/tests/test_helpers.py:17: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
billing/helpers.py:11: in on_enterprise_plan
    plan = Plan.objects.select_related("tier").get(name=owner.plan)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = &lt;QuerySet [&lt;Plan: users-trial&gt;, &lt;Plan: users-free&gt;, &lt;Plan: users-basic&gt;, &lt;Plan: users-pr-inappy&gt;, &lt;Plan: users-pr-inap...lan: users-teamm&gt;, &lt;Plan: users-sentryy&gt;, &lt;Plan: users-sentrym&gt;, &lt;Plan: users-enterprisey&gt;, &lt;Plan: users-enterprisem&gt;]&gt;
args = (), kwargs = {'name': 'users-developer'}, clone = &lt;QuerySet []&gt;
limit = 21, num = 0

    def get(self, *args, **kwargs):
        """
        Perform the query and return a single object matching the given
        keyword arguments.
        """
        if self.query.combinator and (args or kwargs):
            raise NotSupportedError(
                "Calling QuerySet.get(...) with filters after %s() is not "
                "supported." % self.query.combinator
            )
        clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs)
        if self.query.can_filter() and not self.query.distinct_fields:
            clone = clone.order_by()
        limit = None
        if (
            not clone.query.select_for_update
            or connections[clone.db].features.supports_select_for_update_with_limit
        ):
            limit = MAX_GET_RESULTS
            clone.query.set_limits(high=limit)
        num = len(clone)
        if num == 1:
            return clone._result_cache[0]
        if not num:
&gt;           raise self.model.DoesNotExist(
                "%s matching query does not exist." % self.model._meta.object_name
            )
E           shared.django_apps.codecov_auth.models.Plan.DoesNotExist: Plan matching query does not exist.

/usr/local/lib/python3.12/site-packages/django/db/models/query.py:637: DoesNotExist
test_apply_cancellation_discount_existing_coupon
Stack Traces | 0.017s run time
self = &lt;services.tests.test_billing.StripeServiceTests testMethod=test_apply_cancellation_discount_existing_coupon&gt;
customer_modify_mock = &lt;MagicMock name='modify' id='140689377339744'&gt;
coupon_create_mock = &lt;MagicMock name='create' id='140689377330048'&gt;

    @patch("services.billing.stripe.Coupon.create")
    @patch("services.billing.stripe.Customer.modify")
    def test_apply_cancellation_discount_existing_coupon(
        self, customer_modify_mock, coupon_create_mock
    ):
        owner = OwnerFactory(
            stripe_customer_id="test-customer-id",
            stripe_subscription_id="test-subscription-id",
            stripe_coupon_id="test-coupon-id",
        )
&gt;       self.stripe.apply_cancellation_discount(owner)

services/tests/test_billing.py:1896: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
services/billing.py:27: in catch_and_raise
    return method(*args, **kwargs)
services/billing.py:713: in apply_cancellation_discount
    plan_service = PlanService(current_org=owner)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = &lt;shared.plan.service.PlanService object at 0x7ff4cc8d7830&gt;
current_org = &lt;Owner: Owner&lt;github/charlesowens&gt;&gt;

    def __init__(self, current_org: Owner):
        """
        Initializes a PlanService object for a specific organization.
    
        Args:
            current_org (Owner): The organization for which the plan service is being initialized.
    
        Raises:
            ValueError: If the organization's plan is unsupported.
        """
        if (
            current_org.service == Service.GITLAB.value
            and current_org.parent_service_id
        ):
            # for GitLab groups and subgroups, use the plan on the root org
            self.current_org = current_org.root_organization
        else:
            self.current_org = current_org
    
        if not Plan.objects.filter(name=self.current_org.plan).exists():
&gt;           raise ValueError("Unsupported plan")
E           ValueError: Unsupported plan

/usr/local/lib/python3.12/site-packages/shared/plan/service.py:54: ValueError

📣 Thoughts on this report? Let Codecov know! | Powered by Codecov

Copy link

codecov bot commented Feb 4, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 95.92%. Comparing base (8ed03b4) to head (e2c35cd).

✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1127   +/-   ##
=======================================
  Coverage   95.92%   95.92%           
=======================================
  Files         492      492           
  Lines       16876    16890   +14     
=======================================
+ Hits        16188    16202   +14     
  Misses        688      688           
Flag Coverage Δ
unit 95.92% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

github-actions bot commented Feb 4, 2025

This PR includes changes to shared. Please review them here: codecov/shared@c8dca74...7ba099f

Copy link

❌ 53 Tests Failed:

Tests completed Failed Passed Skipped
2738 53 2685 6
View the top 3 failed tests by shortest run time
services/tests/test_billing.py::BillingServiceTests::test_update_plan_to_users_basic_sets_plan_if_no_subscription_id
Stack Traces | 0.013s run time
self = <services.tests.test_billing.BillingServiceTests testMethod=test_update_plan_to_users_basic_sets_plan_if_no_subscription_id>
delete_subscription_mock = <MagicMock name='delete_subscription' id='140689237058544'>
modify_subscription_mock = <MagicMock name='modify_subscription' id='140689237052592'>
create_checkout_session_mock = <MagicMock name='create_checkout_session' id='140689217159392'>
set_default_plan_data = <MagicMock name='set_default_plan_data' id='140689217163328'>

    @patch("shared.plan.service.PlanService.set_default_plan_data")
    @patch("services.tests.test_billing.MockPaymentService.create_checkout_session")
    @patch("services.tests.test_billing.MockPaymentService.modify_subscription")
    @patch("services.tests.test_billing.MockPaymentService.delete_subscription")
    def test_update_plan_to_users_basic_sets_plan_if_no_subscription_id(
        self,
        delete_subscription_mock,
        modify_subscription_mock,
        create_checkout_session_mock,
        set_default_plan_data,
    ):
        owner = OwnerFactory()
>       self.billing_service.update_plan(
            owner, {"value": PlanName.BASIC_PLAN_NAME.value}
        )

services/tests/test_billing.py:2162: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
services/billing.py:929: in update_plan
    plan_service = PlanService(current_org=owner)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.plan.service.PlanService object at 0x7ff4cc38f830>
current_org = <Owner: Owner<github/ashley66>>

    def __init__(self, current_org: Owner):
        """
        Initializes a PlanService object for a specific organization.
    
        Args:
            current_org (Owner): The organization for which the plan service is being initialized.
    
        Raises:
            ValueError: If the organization's plan is unsupported.
        """
        if (
            current_org.service == Service.GITLAB.value
            and current_org.parent_service_id
        ):
            # for GitLab groups and subgroups, use the plan on the root org
            self.current_org = current_org.root_organization
        else:
            self.current_org = current_org
    
        if not Plan.objects.filter(name=self.current_org.plan).exists():
>           raise ValueError("Unsupported plan")
E           ValueError: Unsupported plan

.../local/lib/python3.12.../shared/plan/service.py:54: ValueError
billing/tests/test_helpers.py::HelpersTestCase::test_on_enterprise_plan_on_prem
Stack Traces | 0.017s run time
self = <billing.tests.test_helpers.HelpersTestCase testMethod=test_on_enterprise_plan_on_prem>

    @override_settings(IS_ENTERPRISE=True)
    def test_on_enterprise_plan_on_prem(self):
        owner = OwnerFactory()
>       assert on_enterprise_plan(owner) == True

billing/tests/test_helpers.py:17: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
billing/helpers.py:11: in on_enterprise_plan
    plan = Plan.objects.select_related("tier").get(name=owner.plan)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <QuerySet [<Plan: users-trial>, <Plan: users-free>, <Plan: users-basic>, <Plan: users-pr-inappy>, <Plan: users-pr-inap...lan: users-teamm>, <Plan: users-sentryy>, <Plan: users-sentrym>, <Plan: users-enterprisey>, <Plan: users-enterprisem>]>
args = (), kwargs = {'name': 'users-developer'}, clone = <QuerySet []>
limit = 21, num = 0

    def get(self, *args, **kwargs):
        """
        Perform the query and return a single object matching the given
        keyword arguments.
        """
        if self.query.combinator and (args or kwargs):
            raise NotSupportedError(
                "Calling QuerySet.get(...) with filters after %s() is not "
                "supported." % self.query.combinator
            )
        clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs)
        if self.query.can_filter() and not self.query.distinct_fields:
            clone = clone.order_by()
        limit = None
        if (
            not clone.query.select_for_update
            or connections[clone.db].features.supports_select_for_update_with_limit
        ):
            limit = MAX_GET_RESULTS
            clone.query.set_limits(high=limit)
        num = len(clone)
        if num == 1:
            return clone._result_cache[0]
        if not num:
>           raise self.model.DoesNotExist(
                "%s matching query does not exist." % self.model._meta.object_name
            )
E           shared.django_apps.codecov_auth.models.Plan.DoesNotExist: Plan matching query does not exist.

.../local/lib/python3.12.../db/models/query.py:637: DoesNotExist
services/tests/test_billing.py::StripeServiceTests::test_apply_cancellation_discount_existing_coupon
Stack Traces | 0.017s run time
self = <services.tests.test_billing.StripeServiceTests testMethod=test_apply_cancellation_discount_existing_coupon>
customer_modify_mock = <MagicMock name='modify' id='140689377339744'>
coupon_create_mock = <MagicMock name='create' id='140689377330048'>

    @patch("services.billing.stripe.Coupon.create")
    @patch("services.billing.stripe.Customer.modify")
    def test_apply_cancellation_discount_existing_coupon(
        self, customer_modify_mock, coupon_create_mock
    ):
        owner = OwnerFactory(
            stripe_customer_id="test-customer-id",
            stripe_subscription_id="test-subscription-id",
            stripe_coupon_id="test-coupon-id",
        )
>       self.stripe.apply_cancellation_discount(owner)

services/tests/test_billing.py:1896: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
services/billing.py:27: in catch_and_raise
    return method(*args, **kwargs)
services/billing.py:713: in apply_cancellation_discount
    plan_service = PlanService(current_org=owner)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <shared.plan.service.PlanService object at 0x7ff4cc8d7830>
current_org = <Owner: Owner<github/charlesowens>>

    def __init__(self, current_org: Owner):
        """
        Initializes a PlanService object for a specific organization.
    
        Args:
            current_org (Owner): The organization for which the plan service is being initialized.
    
        Raises:
            ValueError: If the organization's plan is unsupported.
        """
        if (
            current_org.service == Service.GITLAB.value
            and current_org.parent_service_id
        ):
            # for GitLab groups and subgroups, use the plan on the root org
            self.current_org = current_org.root_organization
        else:
            self.current_org = current_org
    
        if not Plan.objects.filter(name=self.current_org.plan).exists():
>           raise ValueError("Unsupported plan")
E           ValueError: Unsupported plan

.../local/lib/python3.12.../shared/plan/service.py:54: ValueError

To view more test analytics, go to the Test Analytics Dashboard
📢 Thoughts on this report? Let us know!

@aj-codecov
Copy link

@codecov-ai-reviewer review

Copy link

codecov-ai bot commented Feb 4, 2025

On it! We are reviewing the PR and will provide feedback shortly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants