mainsequence 8.1.1__tar.gz → 8.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. {mainsequence-8.1.1/mainsequence.egg-info → mainsequence-8.1.2}/PKG-INFO +1 -1
  2. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/models_helpers.py +24 -0
  3. {mainsequence-8.1.1 → mainsequence-8.1.2/mainsequence.egg-info}/PKG-INFO +1 -1
  4. {mainsequence-8.1.1 → mainsequence-8.1.2}/pyproject.toml +1 -1
  5. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_filter_normalization.py +89 -0
  6. {mainsequence-8.1.1 → mainsequence-8.1.2}/LICENSE +0 -0
  7. {mainsequence-8.1.1 → mainsequence-8.1.2}/MANIFEST.in +0 -0
  8. {mainsequence-8.1.1 → mainsequence-8.1.2}/README.md +0 -0
  9. {mainsequence-8.1.1 → mainsequence-8.1.2}/agent_scaffold/AGENTS.md +0 -0
  10. {mainsequence-8.1.1 → mainsequence-8.1.2}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md +0 -0
  11. {mainsequence-8.1.1 → mainsequence-8.1.2}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
  12. {mainsequence-8.1.1 → mainsequence-8.1.2}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
  13. {mainsequence-8.1.1 → mainsequence-8.1.2}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
  14. {mainsequence-8.1.1 → mainsequence-8.1.2}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
  15. {mainsequence-8.1.1 → mainsequence-8.1.2}/agent_scaffold/skills/data_publishing/time_index_table_updates/SKILL.md +0 -0
  16. {mainsequence-8.1.1 → mainsequence-8.1.2}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
  17. {mainsequence-8.1.1 → mainsequence-8.1.2}/agent_scaffold/skills/maintenance/code_repository_maintenance/SKILL.md +0 -0
  18. {mainsequence-8.1.1 → mainsequence-8.1.2}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
  19. {mainsequence-8.1.1 → mainsequence-8.1.2}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
  20. {mainsequence-8.1.1 → mainsequence-8.1.2}/agent_scaffold/skills/sdk_code_repository_execution/SKILL.md +0 -0
  21. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/__init__.py +0 -0
  22. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/__main__.py +0 -0
  23. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/bootstrap.py +0 -0
  24. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/cli/__init__.py +0 -0
  25. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/cli/api.py +0 -0
  26. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/cli/browser_auth.py +0 -0
  27. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/cli/cli.py +0 -0
  28. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/cli/code_repository_status.py +0 -0
  29. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/cli/config.py +0 -0
  30. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/cli/docker_utils.py +0 -0
  31. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/cli/doctor.py +0 -0
  32. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/cli/local_ops.py +0 -0
  33. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/cli/migrations.py +0 -0
  34. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/cli/model_filters.py +0 -0
  35. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/cli/pydantic_cli.py +0 -0
  36. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/cli/sdk_utils.py +0 -0
  37. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/cli/ssh_utils.py +0 -0
  38. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/cli/ui.py +0 -0
  39. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/__init__.py +0 -0
  40. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/agent_runtime_models.py +0 -0
  41. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/base.py +0 -0
  42. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/client.py +0 -0
  43. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/compute_validation.py +0 -0
  44. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
  45. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
  46. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
  47. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
  48. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/dtype_codec.py +0 -0
  49. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/exceptions.py +0 -0
  50. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/metatables/__init__.py +0 -0
  51. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/metatables/core.py +0 -0
  52. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/models_foundry.py +0 -0
  53. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/models_user.py +0 -0
  54. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/observability.py +0 -0
  55. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/client/utils.py +0 -0
  56. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/code_repository_context.py +0 -0
  57. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/code_repository_skills.py +0 -0
  58. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/defaults.py +0 -0
  59. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/instrumentation/__init__.py +0 -0
  60. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/instrumentation/utils.py +0 -0
  61. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/logconf.py +0 -0
  62. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/__init__.py +0 -0
  63. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/__main__.py +0 -0
  64. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
  65. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
  66. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/future_registry.py +0 -0
  67. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/hashing.py +0 -0
  68. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/migrations/__init__.py +0 -0
  69. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/migrations/alembic.py +0 -0
  70. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/migrations/env.py +0 -0
  71. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/migrations/provider.py +0 -0
  72. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/migrations/registry.py +0 -0
  73. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
  74. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
  75. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
  76. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
  77. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
  78. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/schema_names.py +0 -0
  79. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
  80. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/time_index_table_refs.py +0 -0
  81. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/time_index_table_updates/__init__.py +0 -0
  82. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/time_index_table_updates/configuration.py +0 -0
  83. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/time_index_table_updates/dependencies.py +0 -0
  84. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/time_index_table_updates/managers.py +0 -0
  85. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/time_index_table_updates/namespacing.py +0 -0
  86. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/time_index_table_updates/runner.py +0 -0
  87. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/time_index_table_updates/updaters.py +0 -0
  88. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/meta_tables/time_index_table_updates/utils.py +0 -0
  89. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/repository_identity_security.py +0 -0
  90. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/runtime_flags.py +0 -0
  91. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence/scaffold_skills.py +0 -0
  92. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence.egg-info/SOURCES.txt +0 -0
  93. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence.egg-info/dependency_links.txt +0 -0
  94. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence.egg-info/entry_points.txt +0 -0
  95. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence.egg-info/requires.txt +0 -0
  96. {mainsequence-8.1.1 → mainsequence-8.1.2}/mainsequence.egg-info/top_level.txt +0 -0
  97. {mainsequence-8.1.1 → mainsequence-8.1.2}/setup.cfg +0 -0
  98. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/fixtures/time_index_table_update_hash_v2_golden.json +0 -0
  99. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_auth_precedence.py +0 -0
  100. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_canonical_api_route_contract.py +0 -0
  101. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_cli.py +0 -0
  102. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_cli_browser_auth.py +0 -0
  103. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_cli_migrations.py +0 -0
  104. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_client.py +0 -0
  105. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_code_repository_batch_jobs_from_file.py +0 -0
  106. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_code_repository_branch_contract.py +0 -0
  107. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_code_repository_documentation_contract.py +0 -0
  108. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_code_repository_runtime_context.py +0 -0
  109. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_code_repository_skills.py +0 -0
  110. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_dependency_extras.py +0 -0
  111. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_duckdb_interface_dimensions.py +0 -0
  112. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_environment_resource_context.py +0 -0
  113. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_environment_response_contracts.py +0 -0
  114. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_instrumentation.py +0 -0
  115. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_local_ops.py +0 -0
  116. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_logconf.py +0 -0
  117. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_meta_table_migrations.py +0 -0
  118. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_meta_tables_client_models.py +0 -0
  119. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -0
  120. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_models_user_request_bound_auth.py +0 -0
  121. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_notification_uid_contract.py +0 -0
  122. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_observability_client.py +0 -0
  123. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_pod_project_resolution.py +0 -0
  124. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_scaffold_skills.py +0 -0
  125. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_schema_names.py +0 -0
  126. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_secret_client_model.py +0 -0
  127. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_source_table_configuration.py +0 -0
  128. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_sqlite_interface_dimensions.py +0 -0
  129. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_ssh_utils.py +0 -0
  130. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_time_index_table_access_dimension_audit.py +0 -0
  131. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_time_index_table_dimension_queries.py +0 -0
  132. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_time_index_table_update_configuration.py +0 -0
  133. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_time_index_table_update_configuration_client.py +0 -0
  134. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_time_index_table_update_flow.py +0 -0
  135. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_time_index_table_update_hard_cut.py +0 -0
  136. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_update_runner_uid_runtime.py +0 -0
  137. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_update_statistics.py +0 -0
  138. {mainsequence-8.1.1 → mainsequence-8.1.2}/tests/test_update_uid_guards.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 8.1.1
3
+ Version: 8.1.2
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: LicenseRef-MainSequence-Proprietary
@@ -1397,6 +1397,29 @@ class DeploymentRunPipeline(BaseModel):
1397
1397
  steps: list[DeploymentRunStep] = Field(default_factory=list)
1398
1398
 
1399
1399
 
1400
+ class DeploymentRunBillingComponents(BasePydanticModel):
1401
+ image_build: Decimal | None = Field(max_digits=18, decimal_places=6)
1402
+ image_registry_storage: Decimal | None = Field(max_digits=18, decimal_places=6)
1403
+ image_registry_service: Decimal | None = Field(max_digits=18, decimal_places=6)
1404
+
1405
+
1406
+ class DeploymentRunBilling(BasePydanticModel):
1407
+ scope: Literal["image_lifecycle"]
1408
+ total_cost: Decimal | None = Field(max_digits=18, decimal_places=6)
1409
+ currency: str = Field(min_length=1)
1410
+ pricing_state: Literal[
1411
+ "priced",
1412
+ "partial",
1413
+ "pending",
1414
+ "unavailable",
1415
+ "failed",
1416
+ ]
1417
+ components: DeploymentRunBillingComponents
1418
+ priced_rows: int = Field(ge=0)
1419
+ unpriced_rows: int = Field(ge=0)
1420
+ reused_image_count: int = Field(ge=0)
1421
+
1422
+
1400
1423
  class DeploymentRunLogEntry(BaseModel):
1401
1424
  sequence: int
1402
1425
  timestamp: datetime.datetime | None = None
@@ -1473,6 +1496,7 @@ class DeploymentRun(CurrentCodeRepositoryBranchCollectionMixin, BaseObjectOrm, B
1473
1496
  builder_runtime: str = ""
1474
1497
  logs: DeploymentRunLogReference
1475
1498
  error: DeploymentRunError | None = None
1499
+ billing: DeploymentRunBilling
1476
1500
 
1477
1501
  def get_logs(
1478
1502
  self,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 8.1.1
3
+ Version: 8.1.2
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: LicenseRef-MainSequence-Proprietary
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "mainsequence"
7
- version = "8.1.1"
7
+ version = "8.1.2"
8
8
  description = "Main Sequence SDK "
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -3,6 +3,7 @@ import datetime
3
3
  import json
4
4
  import pathlib
5
5
  import uuid
6
+ from decimal import Decimal
6
7
  from types import SimpleNamespace
7
8
 
8
9
  import pytest
@@ -3145,6 +3146,83 @@ def _resource_release_pipeline_payload(*, running_step: str | None = None):
3145
3146
  }
3146
3147
 
3147
3148
 
3149
+ def _deployment_run_billing_payload(
3150
+ *,
3151
+ pricing_state: str = "priced",
3152
+ total_cost: str | None = "0.000000",
3153
+ ) -> dict:
3154
+ return {
3155
+ "scope": "image_lifecycle",
3156
+ "total_cost": total_cost,
3157
+ "currency": "USD",
3158
+ "pricing_state": pricing_state,
3159
+ "components": {
3160
+ "image_build": total_cost,
3161
+ "image_registry_storage": "0.000000" if total_cost is not None else None,
3162
+ "image_registry_service": "0.000000" if total_cost is not None else None,
3163
+ },
3164
+ "priced_rows": 3 if pricing_state == "priced" else 0,
3165
+ "unpriced_rows": 0 if pricing_state == "priced" else 3,
3166
+ "reused_image_count": 0,
3167
+ }
3168
+
3169
+
3170
+ @pytest.mark.parametrize(
3171
+ "pricing_state",
3172
+ ["priced", "partial", "pending", "unavailable", "failed"],
3173
+ )
3174
+ def test_deployment_run_billing_parses_every_backend_pricing_state(pricing_state):
3175
+ total_cost = "1.250000" if pricing_state in {"priced", "partial"} else None
3176
+
3177
+ billing = models_helpers_mod.DeploymentRunBilling.model_validate(
3178
+ _deployment_run_billing_payload(
3179
+ pricing_state=pricing_state,
3180
+ total_cost=total_cost,
3181
+ )
3182
+ )
3183
+
3184
+ assert billing.pricing_state == pricing_state
3185
+ assert billing.total_cost == (Decimal(total_cost) if total_cost is not None else None)
3186
+ assert billing.components.image_build == billing.total_cost
3187
+
3188
+
3189
+ def test_deployment_run_billing_contract_is_complete_and_closed():
3190
+ payload = _deployment_run_billing_payload()
3191
+ for field_name in (
3192
+ "scope",
3193
+ "total_cost",
3194
+ "currency",
3195
+ "pricing_state",
3196
+ "components",
3197
+ "priced_rows",
3198
+ "unpriced_rows",
3199
+ "reused_image_count",
3200
+ ):
3201
+ incomplete = dict(payload)
3202
+ incomplete.pop(field_name)
3203
+ with pytest.raises(ValidationError, match=field_name):
3204
+ models_helpers_mod.DeploymentRunBilling.model_validate(incomplete)
3205
+
3206
+ with pytest.raises(ValidationError, match="extra_forbidden"):
3207
+ models_helpers_mod.DeploymentRunBilling.model_validate(
3208
+ payload | {"future_billing_field": "value"}
3209
+ )
3210
+
3211
+ with pytest.raises(ValidationError, match="extra_forbidden"):
3212
+ models_helpers_mod.DeploymentRunBilling.model_validate(
3213
+ payload
3214
+ | {
3215
+ "components": payload["components"]
3216
+ | {"future_component": "0.000000"}
3217
+ }
3218
+ )
3219
+
3220
+ with pytest.raises(ValidationError, match="greater_than_equal"):
3221
+ models_helpers_mod.DeploymentRunBilling.model_validate(
3222
+ payload | {"unpriced_rows": -1}
3223
+ )
3224
+
3225
+
3148
3226
  def test_resource_release_deploy_current_version_posts_detail_action(monkeypatch):
3149
3227
  captured = {}
3150
3228
  release_uid = "2f4c4c3d-5669-4da5-9d86-b84633c1e6ed"
@@ -3189,6 +3267,7 @@ def test_resource_release_deploy_current_version_posts_detail_action(monkeypatch
3189
3267
  "retention_expires_at": None,
3190
3268
  },
3191
3269
  "error": None,
3270
+ "billing": _deployment_run_billing_payload(),
3192
3271
  }
3193
3272
 
3194
3273
  def _fake_make_request(*, s, loaders, r_type, url, payload, time_out=None):
@@ -3213,6 +3292,7 @@ def test_resource_release_deploy_current_version_posts_detail_action(monkeypatch
3213
3292
  assert run.builder_runtime == ""
3214
3293
  assert run.logs.state == "available"
3215
3294
  assert run.error is None
3295
+ assert run.billing.total_cost == Decimal("0.000000")
3216
3296
  assert captured == {
3217
3297
  "r_type": "POST",
3218
3298
  "url": (
@@ -3256,6 +3336,7 @@ def test_deployment_run_collection_and_detail_use_unified_resource_release_contr
3256
3336
  "retention_expires_at": None,
3257
3337
  },
3258
3338
  "error": None,
3339
+ "billing": _deployment_run_billing_payload(),
3259
3340
  }
3260
3341
 
3261
3342
  collection_payload = {
@@ -3311,6 +3392,8 @@ def test_deployment_run_collection_and_detail_use_unified_resource_release_contr
3311
3392
  assert detail.builder_runtime == ""
3312
3393
  assert detail.logs.state == "available"
3313
3394
  assert detail.error is None
3395
+ assert runs[0].billing.pricing_state == "priced"
3396
+ assert detail.billing.components.image_registry_storage == Decimal("0.000000")
3314
3397
  assert captured[0]["payload"] == {
3315
3398
  "params": {
3316
3399
  "code_repository_branch_uid": CODE_REPOSITORY_BRANCH_UID,
@@ -3350,6 +3433,10 @@ def test_unified_deployment_run_models_and_filters(monkeypatch):
3350
3433
  "retention_expires_at": None,
3351
3434
  },
3352
3435
  "error": None,
3436
+ "billing": _deployment_run_billing_payload(
3437
+ pricing_state="pending",
3438
+ total_cost=None,
3439
+ ),
3353
3440
  }
3354
3441
  )
3355
3442
 
@@ -3367,6 +3454,8 @@ def test_unified_deployment_run_models_and_filters(monkeypatch):
3367
3454
  assert run.pipeline.steps[4].state == "pending"
3368
3455
  assert run.builder_image == "us-docker.pkg.dev/platform/static-builder:latest"
3369
3456
  assert run.builder_runtime == "nodejs22"
3457
+ assert run.billing.pricing_state == "pending"
3458
+ assert run.billing.total_cost is None
3370
3459
  assert normalized == {
3371
3460
  "code_repository_branch_uid": code_repository_branch_uid,
3372
3461
  "target_type__in": ["resource_release", "static_site"],
File without changes
File without changes
File without changes
File without changes