Skip to content

Commit 0e99d82

Browse files
committed
Merge remote-tracking branch 'upstream/master' into 2025/fix/ooil1
2 parents 1e8f811 + 638b592 commit 0e99d82

File tree

94 files changed

+1222
-643
lines changed

Some content is hidden

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

94 files changed

+1222
-643
lines changed

.env-devel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ WEBSERVER_GARBAGE_COLLECTOR=null
371371
WEBSERVER_GROUPS=1
372372
WEBSERVER_GUNICORN_CMD_ARGS=--timeout=180
373373
WEBSERVER_HOST=webserver
374+
WEBSERVER_LICENSES=true
374375
WEBSERVER_LOGIN={}
375376
WEBSERVER_LOGLEVEL=INFO
376377
WEBSERVER_META_MODELING=1

.github/mergify.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# NOTE: the PR is added to the queue when all checks have passed
2+
# and the CI is fully green.
3+
# If the PR is behind the queue will take care of updating it
4+
queue_rules:
5+
- name: default
6+
queue_conditions:
7+
# general prerequisits fo accept the PR in the queue
8+
- label=🤖-automerge # let Mergify know that the PR can be merged (added manually)
9+
- label!=🤖-do-not-merge # block Mergify from merging the PR (added manually)
10+
- base=master
11+
- -draft # PR is not in draft state
12+
- -conflict # No merge conflicts
13+
14+
# Check for required reviews
15+
- "#approved-reviews-by>=2" # Requires 2 approving reviews
16+
- "#changes-requested-reviews-by=0" # No changes requested
17+
- "#review-threads-unresolved=0" # All review threads resolved
18+
19+
merge_conditions:
20+
# list of CI checks that need to pass
21+
- check-success=unit-tests
22+
- check-success=integration-tests
23+
- check-success=system-tests
24+
25+
# NOTE: in case of flaky tests you above checks will fail
26+
# the PR will be removed from the queue.
27+
# This retries the checks, as soon as they become green,
28+
# the PR will be pusehd to the queu again
29+
pull_request_rules:
30+
- name: retry CI on fails (used for flaky tests)
31+
conditions:
32+
- label=🤖-automerge
33+
- label!=🤖-do-not-merge
34+
- base=master
35+
- or:
36+
- check-failure=unit-tests
37+
- check-failure=integration-tests
38+
- check-failure=system-tests
39+
actions:
40+
github_actions:
41+
workflow:
42+
dispatch:
43+
- workflow: .github/workflows/ci-testing-deploy.yml

.ruff.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
select = [
2+
lint.select = [
33
"A", # [https://pypi.org/project/flake8-builtins/]
44
"ARG", # [https://pypi.org/project/flake8-unused-arguments/]
55
"ASYNC", # [https://pypi.org/project/flake8-async/]
@@ -40,7 +40,7 @@ select = [
4040
"W", # [https://pypi.org/project/pycodestyle/] warnings
4141
"YTT", # [https://pypi.org/project/flake8-2020/]
4242
]
43-
ignore = [
43+
lint.ignore = [
4444
"E501", # line too long, handled by black
4545
"S101", # use of `assert` detected hanbled by pylance, does not support noseq
4646
"TID252", # [*] Relative imports from parent modules are banned
@@ -50,7 +50,7 @@ ignore = [
5050
target-version = "py311"
5151

5252

53-
[per-file-ignores]
53+
[lint.per-file-ignores]
5454
"**/{tests,pytest_simcore}/**" = [
5555
"T201", # print found
5656
"ARG001", # unused function argument
@@ -64,10 +64,10 @@ target-version = "py311"
6464
"FBT001", # Boolean positional arg in function definition
6565
]
6666

67-
[flake8-pytest-style]
67+
[lint.flake8-pytest-style]
6868
fixture-parentheses = false
6969
parametrize-names-type = "csv"
7070

7171

72-
[pylint]
72+
[lint.pylint]
7373
max-args = 10

api/specs/web-server/_licensed_items.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
from models_library.generics import Envelope
1515
from models_library.rest_error import EnvelopedError
1616
from simcore_service_webserver._meta import API_VTAG
17-
from simcore_service_webserver.licenses._exceptions_handlers import _TO_HTTP_ERROR_MAP
18-
from simcore_service_webserver.licenses._models import (
17+
from simcore_service_webserver.licenses._common.exceptions_handlers import (
18+
_TO_HTTP_ERROR_MAP,
19+
)
20+
from simcore_service_webserver.licenses._common.models import (
1921
LicensedItemsBodyParams,
2022
LicensedItemsListQueryParams,
2123
LicensedItemsPathParams,

api/specs/web-server/_licensed_items_checkouts.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
from models_library.rest_error import EnvelopedError
1818
from models_library.rest_pagination import Page
1919
from simcore_service_webserver._meta import API_VTAG
20-
from simcore_service_webserver.licenses._exceptions_handlers import _TO_HTTP_ERROR_MAP
20+
from simcore_service_webserver.licenses._common.exceptions_handlers import (
21+
_TO_HTTP_ERROR_MAP,
22+
)
2123
from simcore_service_webserver.licenses._licensed_items_checkouts_models import (
2224
LicensedItemCheckoutPathParams,
2325
LicensedItemsCheckoutsListQueryParams,

api/specs/web-server/_licensed_items_purchases.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
from models_library.rest_error import EnvelopedError
1818
from models_library.rest_pagination import Page
1919
from simcore_service_webserver._meta import API_VTAG
20-
from simcore_service_webserver.licenses._exceptions_handlers import _TO_HTTP_ERROR_MAP
21-
from simcore_service_webserver.licenses._models import (
20+
from simcore_service_webserver.licenses._common.exceptions_handlers import (
21+
_TO_HTTP_ERROR_MAP,
22+
)
23+
from simcore_service_webserver.licenses._common.models import (
2224
LicensedItemsPurchasesListQueryParams,
2325
LicensedItemsPurchasesPathParams,
2426
)

api/specs/web-server/_resource_usage.py

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
CreatePricingPlanBodyParams,
2222
CreatePricingUnitBodyParams,
2323
PricingPlanAdminGet,
24+
PricingPlanGet,
2425
PricingPlanToServiceAdminGet,
2526
PricingUnitAdminGet,
2627
PricingUnitGet,
@@ -29,15 +30,16 @@
2930
UpdatePricingUnitBodyParams,
3031
)
3132
from models_library.generics import Envelope
33+
from models_library.rest_pagination import Page, PageQueryParameters
3234
from simcore_service_webserver._meta import API_VTAG
33-
from simcore_service_webserver.resource_usage._pricing_plans_admin_handlers import (
35+
from simcore_service_webserver.resource_usage._pricing_plans_admin_rest import (
3436
PricingPlanGetPathParams,
3537
PricingUnitGetPathParams,
3638
)
37-
from simcore_service_webserver.resource_usage._pricing_plans_handlers import (
39+
from simcore_service_webserver.resource_usage._pricing_plans_rest import (
3840
PricingPlanUnitGetPathParams,
3941
)
40-
from simcore_service_webserver.resource_usage._service_runs_handlers import (
42+
from simcore_service_webserver.resource_usage._service_runs_rest import (
4143
ServicesAggregatedUsagesListQueryParams,
4244
ServicesResourceUsagesListQueryParams,
4345
ServicesResourceUsagesReportQueryParams,
@@ -48,7 +50,7 @@
4850

4951
@router.get(
5052
"/services/-/resource-usages",
51-
response_model=Envelope[list[ServiceRunGet]],
53+
response_model=Page[ServiceRunGet],
5254
summary="Retrieve finished and currently running user services"
5355
" (user and product are taken from context, optionally wallet_id parameter might be provided).",
5456
tags=["usage"],
@@ -61,7 +63,7 @@ async def list_resource_usage_services(
6163

6264
@router.get(
6365
"/services/-/aggregated-usages",
64-
response_model=Envelope[list[OsparcCreditsAggregatedByServiceGet]],
66+
response_model=Page[OsparcCreditsAggregatedByServiceGet],
6567
summary="Used credits based on aggregate by type, currently supported `services`"
6668
". (user and product are taken from context, optionally wallet_id parameter might be provided).",
6769
tags=["usage"],
@@ -93,7 +95,6 @@ async def export_resource_usage_services(
9395
@router.get(
9496
"/pricing-plans/{pricing_plan_id}/pricing-units/{pricing_unit_id}",
9597
response_model=Envelope[PricingUnitGet],
96-
summary="Retrieve detail information about pricing unit",
9798
tags=["pricing-plans"],
9899
)
99100
async def get_pricing_plan_unit(
@@ -102,27 +103,50 @@ async def get_pricing_plan_unit(
102103
...
103104

104105

106+
@router.get(
107+
"/pricing-plans",
108+
response_model=Page[PricingPlanGet],
109+
tags=["pricing-plans"],
110+
description="To keep the listing lightweight, the pricingUnits field is None.",
111+
)
112+
async def list_pricing_plans(
113+
_query: Annotated[as_query(PageQueryParameters), Depends()]
114+
):
115+
...
116+
117+
118+
@router.get(
119+
"/pricing-plans/{pricing_plan_id}",
120+
response_model=Envelope[PricingPlanGet],
121+
tags=["pricing-plans"],
122+
)
123+
async def get_pricing_plan(
124+
_path: Annotated[PricingPlanGetPathParams, Depends()],
125+
):
126+
...
127+
128+
105129
## Pricing plans for Admin panel
106130

107131

108132
@router.get(
109133
"/admin/pricing-plans",
110-
response_model=Envelope[list[PricingPlanAdminGet]],
111-
summary="List pricing plans",
134+
response_model=Page[PricingPlanAdminGet],
112135
tags=["admin"],
113136
description="To keep the listing lightweight, the pricingUnits field is None.",
114137
)
115-
async def list_pricing_plans():
138+
async def list_pricing_plans_for_admin_user(
139+
_query: Annotated[as_query(PageQueryParameters), Depends()]
140+
):
116141
...
117142

118143

119144
@router.get(
120145
"/admin/pricing-plans/{pricing_plan_id}",
121146
response_model=Envelope[PricingPlanAdminGet],
122-
summary="Retrieve detail information about pricing plan",
123147
tags=["admin"],
124148
)
125-
async def get_pricing_plan(
149+
async def get_pricing_plan_for_admin_user(
126150
_path: Annotated[PricingPlanGetPathParams, Depends()],
127151
):
128152
...
@@ -131,7 +155,6 @@ async def get_pricing_plan(
131155
@router.post(
132156
"/admin/pricing-plans",
133157
response_model=Envelope[PricingPlanAdminGet],
134-
summary="Create pricing plan",
135158
tags=["admin"],
136159
)
137160
async def create_pricing_plan(
@@ -143,7 +166,6 @@ async def create_pricing_plan(
143166
@router.put(
144167
"/admin/pricing-plans/{pricing_plan_id}",
145168
response_model=Envelope[PricingPlanAdminGet],
146-
summary="Update detail information about pricing plan",
147169
tags=["admin"],
148170
)
149171
async def update_pricing_plan(
@@ -159,7 +181,6 @@ async def update_pricing_plan(
159181
@router.get(
160182
"/admin/pricing-plans/{pricing_plan_id}/pricing-units/{pricing_unit_id}",
161183
response_model=Envelope[PricingUnitAdminGet],
162-
summary="Retrieve detail information about pricing unit",
163184
tags=["admin"],
164185
)
165186
async def get_pricing_unit(
@@ -171,7 +192,6 @@ async def get_pricing_unit(
171192
@router.post(
172193
"/admin/pricing-plans/{pricing_plan_id}/pricing-units",
173194
response_model=Envelope[PricingUnitAdminGet],
174-
summary="Create pricing unit",
175195
tags=["admin"],
176196
)
177197
async def create_pricing_unit(
@@ -184,7 +204,6 @@ async def create_pricing_unit(
184204
@router.put(
185205
"/admin/pricing-plans/{pricing_plan_id}/pricing-units/{pricing_unit_id}",
186206
response_model=Envelope[PricingUnitAdminGet],
187-
summary="Update detail information about pricing plan",
188207
tags=["admin"],
189208
)
190209
async def update_pricing_unit(
@@ -200,7 +219,6 @@ async def update_pricing_unit(
200219
@router.get(
201220
"/admin/pricing-plans/{pricing_plan_id}/billable-services",
202221
response_model=Envelope[list[PricingPlanToServiceAdminGet]],
203-
summary="List services that are connected to the provided pricing plan",
204222
tags=["admin"],
205223
)
206224
async def list_connected_services_to_pricing_plan(
@@ -212,7 +230,6 @@ async def list_connected_services_to_pricing_plan(
212230
@router.post(
213231
"/admin/pricing-plans/{pricing_plan_id}/billable-services",
214232
response_model=Envelope[PricingPlanToServiceAdminGet],
215-
summary="Connect service with pricing plan",
216233
tags=["admin"],
217234
)
218235
async def connect_service_to_pricing_plan(

packages/models-library/src/models_library/api_schemas_resource_usage_tracker/licensed_items_checkouts.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class LicensedItemCheckoutGet(BaseModel):
1717
licensed_item_id: LicensedItemID
1818
wallet_id: WalletID
1919
user_id: UserID
20+
user_email: str
2021
product_name: ProductName
2122
service_run_id: ServiceRunID
2223
started_at: datetime
@@ -31,6 +32,7 @@ class LicensedItemCheckoutGet(BaseModel):
3132
"licensed_item_id": "303942ef-6d31-4ba8-afbe-dbb1fce2a953",
3233
"wallet_id": 1,
3334
"user_id": 1,
35+
"user_email": "[email protected]",
3436
"product_name": "osparc",
3537
"service_run_id": "run_1",
3638
"started_at": "2023-01-11 13:11:47.293595",

packages/models-library/src/models_library/api_schemas_resource_usage_tracker/licensed_items_purchases.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class LicensedItemPurchaseGet(BaseModel):
2525
expire_at: datetime
2626
num_of_seats: int
2727
purchased_by_user: UserID
28+
user_email: str
2829
purchased_at: datetime
2930
modified: datetime
3031

@@ -43,6 +44,7 @@ class LicensedItemPurchaseGet(BaseModel):
4344
"expire_at": "2023-01-11 13:11:47.293595",
4445
"num_of_seats": 1,
4546
"purchased_by_user": 1,
47+
"user_email": "[email protected]",
4648
"purchased_at": "2023-01-11 13:11:47.293595",
4749
"modified": "2023-01-11 13:11:47.293595",
4850
}

packages/models-library/src/models_library/api_schemas_resource_usage_tracker/pricing_plans.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from datetime import datetime
22
from decimal import Decimal
3+
from typing import NamedTuple
34

4-
from pydantic import BaseModel, ConfigDict
5+
from pydantic import BaseModel, ConfigDict, PositiveInt
56

67
from ..resource_tracker import (
78
HardwareInfo,
@@ -76,6 +77,11 @@ class PricingPlanGet(BaseModel):
7677
)
7778

7879

80+
class PricingPlanPage(NamedTuple):
81+
items: list[PricingPlanGet]
82+
total: PositiveInt
83+
84+
7985
class PricingPlanToServiceGet(BaseModel):
8086
pricing_plan_id: PricingPlanId
8187
service_key: ServiceKey

0 commit comments

Comments
 (0)