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: add plan tier service #150

Merged
merged 10 commits into from Sep 25, 2023
Merged

feat: add plan tier service #150

merged 10 commits into from Sep 25, 2023

Conversation

adrian-codecov
Copy link
Contributor

Purpose/Motivation

We need a way to differentiate a tier based on it's plan. This is an evolving tier so this is the first pass at this.

What does this PR do?

  • Add tier service + test w/ barebones differentiation of plans based on their tiers
  • Add resolvers + test to expose that to the client

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
Copy link

codecov bot commented Sep 20, 2023

Codecov Report

Merging #150 (0f511b6) into main (fc9553f) will increase coverage by 0.01%.
The diff coverage is 100.00%.

@@           Coverage Diff           @@
##            main    #150     +/-   ##
=======================================
+ Coverage   95.44   95.45   +0.01     
=======================================
  Files        709     709             
  Lines      15201   15223     +22     
=======================================
+ Hits       14508   14530     +22     
  Misses       693     693             
Flag Coverage Δ
unit 95.60% <100.00%> (+<0.01%) ⬆️
unit-latest-uploader 95.60% <100.00%> (+<0.01%) ⬆️

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

Files Coverage Δ
graphql_api/types/enums/enum_types.py 100.00% <100.00%> (ø)
graphql_api/types/plan/plan.py 98.11% <100.00%> (+0.15%) ⬆️
...i/types/plan_representation/plan_representation.py 97.14% <100.00%> (ø)
plan/constants.py 100.00% <100.00%> (ø)
plan/service.py 96.11% <100.00%> (+0.11%) ⬆️
plan/test_plan.py 100.00% <100.00%> (ø)

@codecov-public-qa
Copy link

codecov-public-qa bot commented Sep 20, 2023

Codecov Report

Merging #150 (0f511b6) into main (fc9553f) will increase coverage by 0.00%.
The diff coverage is 100.00%.

Impacted file tree graph

@@           Coverage Diff           @@
##             main     #150   +/-   ##
=======================================
  Coverage   95.52%   95.53%           
=======================================
  Files         594      594           
  Lines       14801    14823   +22     
=======================================
+ Hits        14139    14161   +22     
  Misses        662      662           
Flag Coverage Δ
unit 95.53% <100.00%> (+<0.01%) ⬆️
unit-latest-uploader 95.53% <100.00%> (+<0.01%) ⬆️

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

Files Changed Coverage Δ
graphql_api/types/enums/enum_types.py 100.00% <100.00%> (ø)
graphql_api/types/plan/plan.py 98.11% <100.00%> (+0.15%) ⬆️
...i/types/plan_representation/plan_representation.py 97.14% <100.00%> (ø)
plan/constants.py 100.00% <100.00%> (ø)
plan/service.py 95.14% <100.00%> (+0.14%) ⬆️
plan/test_plan.py 100.00% <100.00%> (ø)

Impacted file tree graph

@codecov-staging
Copy link

codecov-staging bot commented Sep 20, 2023

Codecov Report

All modified lines are covered by tests ✅

📢 Thoughts on this report? Let us know!.

@@ -23,6 +23,7 @@ type Owner {
orgUploadToken: String
defaultOrgUsername: String
isCurrentUserActivated: Boolean!
tier: TierName
Copy link
Contributor

Choose a reason for hiding this comment

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

The return type of the resolver is TierName which indicates that it can't be null. Should this be TierName! to match? Or should the return type of the resolver be Optional[TierName]?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, I'll make this non-nullable

ENTERPRISE_TIER_PLAN_NAMES = [
PlanName.ENTERPRISE_CLOUD_MONTHLY.value,
PlanName.ENTERPRISE_CLOUD_YEARLY.value,
]
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it make sense to just include a tier with each plan representation? Then we wouldn't need to keep these lists in sync and might simplify the implementation of TierService

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a good idea, my only hesitance is anticipating if a tier could ever not be strictly tied to your plan. If so, it almost feels like there's no need for a tier service altogether, and just a property of the plan service, so like

<some>_PLAN_REPRESENTATIONS = {
    PlanName.<some>_PLAN_NAME.value: PlanData(
        ...
        tier=<some tier>,
        ...
    ),
  }
}


class PlanService():
...
def tier(self) -> TierName:
  return self.plan_data.tier

@@ -47,6 +50,8 @@ class PlanPrice(enum.Enum):
CODECOV_FREE = 0
CODECOV_BASIC = 0
CODECOV_TRIAL = 0
LITE_MONTHLY = 6
LITE_YEARLY = 8
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These values are not defined yet and subject to change

@@ -84,6 +97,7 @@ class PlanData:
"Unlimited private repositories",
"Priority Support",
],
tier_name=TierName.PRO.value,
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the types are slightly off here. TierName.PRO has type TierName but TierName.PRO.value has type str

@plan_bindable.field("tierName")
@convert_kwargs_to_snake_case
def resolve_tier_name(plan_service: PlanService, info) -> TierName:
return plan_service.tier_name
Copy link
Contributor

Choose a reason for hiding this comment

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

This is where you could call .value on the enum. The return type would be str.

@@ -6,6 +6,7 @@ type Plan {
pretrialUsersCount: Int
marketingName: String!
planName: String!
tierName: String!
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we use the GraphQL enum anywhere? Should this be tierName: TierName! instead?

@adrian-codecov adrian-codecov merged commit 309c6ce into main Sep 25, 2023
22 of 23 checks passed
@adrian-codecov adrian-codecov deleted the 412-plan-permissions branch September 25, 2023 19:50
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.

None yet

2 participants