mainsequence 6.0.48__tar.gz → 6.0.49__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.
- {mainsequence-6.0.48 → mainsequence-6.0.49}/PKG-INFO +1 -1
- {mainsequence-6.0.48 → mainsequence-6.0.49}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +10 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/models_helpers.py +46 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence.egg-info/PKG-INFO +1 -1
- {mainsequence-6.0.48 → mainsequence-6.0.49}/pyproject.toml +1 -1
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_filter_normalization.py +135 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/LICENSE +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/README.md +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/agent_scaffold/AGENTS.md +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/agent_scaffold/skills/maintenance/project-maintenance/SKILL.md +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/agent_scaffold/skills/sdk_project_execution/SKILL.md +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/__init__.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/__main__.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/bootstrap.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/cli/__init__.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/cli/api.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/cli/browser_auth.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/cli/cli.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/cli/config.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/cli/docker_utils.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/cli/doctor.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/cli/local_ops.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/cli/migrations.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/cli/model_filters.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/cli/project_status.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/cli/pydantic_cli.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/cli/sdk_utils.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/cli/ssh_utils.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/cli/ui.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/__init__.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/agent_runtime_models.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/base.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/client.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/compute_validation.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/dtype_codec.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/exceptions.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/metatables/__init__.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/metatables/core.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/models_foundry.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/models_user.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/observability.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/utils.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/defaults.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/instrumentation/__init__.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/instrumentation/utils.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/logconf.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/__init__.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/__main__.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/data_nodes/__init__.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/data_nodes/build_operations.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/data_nodes/data_nodes.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/data_nodes/models.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/data_nodes/namespacing.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/data_nodes/persist_managers.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/data_nodes/run_operations.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/data_nodes/utils.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/future_registry.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/hashing.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/migrations/__init__.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/migrations/alembic.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/migrations/env.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/migrations/provider.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/migrations/registry.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/schema_names.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/project_context.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/project_skills.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/runtime_flags.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/scaffold_skills.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence.egg-info/SOURCES.txt +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence.egg-info/dependency_links.txt +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence.egg-info/entry_points.txt +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence.egg-info/requires.txt +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence.egg-info/top_level.txt +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/setup.cfg +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_auth_precedence.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_build_operations_hashing.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_canonical_api_route_contract.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_cli.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_cli_browser_auth.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_cli_migrations.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_client.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_data_access_mixin_dimension_audit.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_data_node_storage_dimension_queries.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_data_node_update_flow.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_dependency_extras.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_duckdb_interface_dimensions.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_environment_resource_context.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_environment_response_contracts.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_instrumentation.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_local_ops.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_logconf.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_meta_table_migrations.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_meta_tables_client_models.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_models_user_request_bound_auth.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_notification_uid_contract.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_observability_client.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_pod_project_resolution.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_project_batch_jobs_from_file.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_project_branch_contract.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_project_runtime_context.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_project_skills.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_run_configuration.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_scaffold_skills.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_scheduler_client_model.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_schema_names.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_secret_client_model.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_source_table_configuration.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_sqlite_interface_dimensions.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_ssh_utils.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_update_runner_uid_runtime.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_update_statistics.py +0 -0
- {mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_update_uid_guards.py +0 -0
|
@@ -302,6 +302,16 @@ The SDK surface also accepts:
|
|
|
302
302
|
- `ResourceRelease.deploy_current_version()` for an SDK-triggered manual deployment run; it returns `DeploymentRun`
|
|
303
303
|
- `DeploymentRun.filter(target_type="resource_release", target_uid=release.uid)` to inspect runs for one release
|
|
304
304
|
|
|
305
|
+
Every release also exposes its immutable revision lifecycle:
|
|
306
|
+
|
|
307
|
+
- `desired_revision` is the public UID of the accepted revision being materialized
|
|
308
|
+
- `active_revision` is the public UID of the ready revision currently serving behind the stable release URL
|
|
309
|
+
- the two UIDs may differ while a deployment is running or after a deployment fails
|
|
310
|
+
- `revision_retention_count` is the positive release-owned retention setting; omission on create uses the backend default
|
|
311
|
+
- configure retention with `ResourceRelease.create(..., revision_retention_count=3)` or `release.patch(revision_retention_count=5)`
|
|
312
|
+
|
|
313
|
+
Treat `active_revision` and `desired_revision` as read-only public identities. Do not substitute provider revision names, deployment names, or internal database IDs.
|
|
314
|
+
|
|
305
315
|
Do not claim there is a CLI command for `deploy_current_version` unless the local CLI actually exposes one. In this SDK, the manual detail action is available through the client model.
|
|
306
316
|
|
|
307
317
|
Inspect the unified run's `state`, `phase`, `outcome`, `steps`, `logs`, and `error` fields. Do not use legacy resource-release deployment status fields or filters.
|
|
@@ -1199,6 +1199,33 @@ class ResourceRelease(
|
|
|
1199
1199
|
"The revision is returned by the API and is not part of create requests."
|
|
1200
1200
|
),
|
|
1201
1201
|
)
|
|
1202
|
+
revision_retention_count: PositiveInt = Field(
|
|
1203
|
+
default=3,
|
|
1204
|
+
title="Revision Retention Count",
|
|
1205
|
+
description=(
|
|
1206
|
+
"Number of immutable release revisions retained by the platform. "
|
|
1207
|
+
"This positive release setting can be supplied on create or patch."
|
|
1208
|
+
),
|
|
1209
|
+
examples=[3],
|
|
1210
|
+
)
|
|
1211
|
+
active_revision: str | None = Field(
|
|
1212
|
+
default=None,
|
|
1213
|
+
title="Active Revision UID",
|
|
1214
|
+
description=(
|
|
1215
|
+
"Public UID of the ready immutable revision currently serving behind "
|
|
1216
|
+
"the stable release URL."
|
|
1217
|
+
),
|
|
1218
|
+
examples=["19128ab6-d72f-460c-8525-d758fa92676a", None],
|
|
1219
|
+
)
|
|
1220
|
+
desired_revision: str | None = Field(
|
|
1221
|
+
default=None,
|
|
1222
|
+
title="Desired Revision UID",
|
|
1223
|
+
description=(
|
|
1224
|
+
"Public UID of the accepted immutable revision currently being "
|
|
1225
|
+
"materialized. It may differ from the active revision during deployment."
|
|
1226
|
+
),
|
|
1227
|
+
examples=["2a9370a7-c07f-439c-bcd9-629e3e916699", None],
|
|
1228
|
+
)
|
|
1202
1229
|
cors_allowed_origins: list[str] | None = Field(
|
|
1203
1230
|
default=None,
|
|
1204
1231
|
title="CORS Allowed Origins",
|
|
@@ -1222,6 +1249,7 @@ class ResourceRelease(
|
|
|
1222
1249
|
gpu_type: str | None = None,
|
|
1223
1250
|
spot: bool | None = None,
|
|
1224
1251
|
automatic_deployment: bool | None = None,
|
|
1252
|
+
revision_retention_count: int | None = None,
|
|
1225
1253
|
timeout: int | None = None,
|
|
1226
1254
|
files=None,
|
|
1227
1255
|
) -> ResourceRelease:
|
|
@@ -1268,6 +1296,10 @@ class ResourceRelease(
|
|
|
1268
1296
|
payload["spot"] = bool(spot)
|
|
1269
1297
|
if automatic_deployment is not None:
|
|
1270
1298
|
payload["automatic_deployment"] = bool(automatic_deployment)
|
|
1299
|
+
if revision_retention_count is not None:
|
|
1300
|
+
payload["revision_retention_count"] = cls._normalize_revision_retention_count(
|
|
1301
|
+
revision_retention_count
|
|
1302
|
+
)
|
|
1271
1303
|
|
|
1272
1304
|
request_payload = {"json": cls.serialize_for_json(payload)}
|
|
1273
1305
|
if files:
|
|
@@ -1287,6 +1319,20 @@ class ResourceRelease(
|
|
|
1287
1319
|
|
|
1288
1320
|
return cls(**r.json())
|
|
1289
1321
|
|
|
1322
|
+
@staticmethod
|
|
1323
|
+
def _normalize_revision_retention_count(value: int) -> int:
|
|
1324
|
+
if isinstance(value, bool) or not isinstance(value, int) or value < 1:
|
|
1325
|
+
raise ValueError("revision_retention_count must be a positive integer.")
|
|
1326
|
+
return value
|
|
1327
|
+
|
|
1328
|
+
@classmethod
|
|
1329
|
+
def patch_by_uid(cls, uid: str, *args, _into=None, **kwargs):
|
|
1330
|
+
if "revision_retention_count" in kwargs:
|
|
1331
|
+
kwargs["revision_retention_count"] = cls._normalize_revision_retention_count(
|
|
1332
|
+
kwargs["revision_retention_count"]
|
|
1333
|
+
)
|
|
1334
|
+
return super().patch_by_uid(uid, *args, _into=_into, **kwargs)
|
|
1335
|
+
|
|
1290
1336
|
def deploy_current_version(
|
|
1291
1337
|
self,
|
|
1292
1338
|
*,
|
|
@@ -2538,6 +2538,9 @@ def test_resource_release_model_supports_automatic_deployment_payloads():
|
|
|
2538
2538
|
"tag_regex": None,
|
|
2539
2539
|
"policy_revision": 3,
|
|
2540
2540
|
},
|
|
2541
|
+
"revision_retention_count": 3,
|
|
2542
|
+
"active_revision": None,
|
|
2543
|
+
"desired_revision": "2a9370a7-c07f-439c-bcd9-629e3e916699",
|
|
2541
2544
|
}
|
|
2542
2545
|
)
|
|
2543
2546
|
|
|
@@ -2547,6 +2550,45 @@ def test_resource_release_model_supports_automatic_deployment_payloads():
|
|
|
2547
2550
|
assert release.automatic_redeployment_policy is not None
|
|
2548
2551
|
assert release.automatic_redeployment_policy.tag_regex is None
|
|
2549
2552
|
assert release.automatic_redeployment_policy.policy_revision == 3
|
|
2553
|
+
assert release.revision_retention_count == 3
|
|
2554
|
+
assert release.active_revision is None
|
|
2555
|
+
assert release.desired_revision == "2a9370a7-c07f-439c-bcd9-629e3e916699"
|
|
2556
|
+
|
|
2557
|
+
|
|
2558
|
+
def test_resource_release_filter_accepts_canonical_revision_lifecycle_projection(monkeypatch):
|
|
2559
|
+
release_uid = "2f4c4c3d-5669-4da5-9d86-b84633c1e6ed"
|
|
2560
|
+
desired_revision_uid = "2a9370a7-c07f-439c-bcd9-629e3e916699"
|
|
2561
|
+
response_payload = {
|
|
2562
|
+
"uid": release_uid,
|
|
2563
|
+
"project_branch_uid": PROJECT_BRANCH_UID,
|
|
2564
|
+
"name": "Pricing API",
|
|
2565
|
+
"release_kind": "fastapi",
|
|
2566
|
+
"automatic_deployment": True,
|
|
2567
|
+
"automatic_redeployment_policy": {
|
|
2568
|
+
"tag_regex": None,
|
|
2569
|
+
"policy_revision": 2,
|
|
2570
|
+
},
|
|
2571
|
+
"revision_retention_count": 3,
|
|
2572
|
+
"active_revision": None,
|
|
2573
|
+
"desired_revision": desired_revision_uid,
|
|
2574
|
+
}
|
|
2575
|
+
|
|
2576
|
+
class FakeResponse:
|
|
2577
|
+
status_code = 200
|
|
2578
|
+
|
|
2579
|
+
@staticmethod
|
|
2580
|
+
def json():
|
|
2581
|
+
return [dict(response_payload)]
|
|
2582
|
+
|
|
2583
|
+
monkeypatch.setattr(base_mod, "make_request", lambda **kwargs: FakeResponse())
|
|
2584
|
+
|
|
2585
|
+
releases = models_helpers_mod.ResourceRelease.filter(project_branch_uid=PROJECT_BRANCH_UID)
|
|
2586
|
+
|
|
2587
|
+
assert len(releases) == 1
|
|
2588
|
+
assert releases[0].uid == release_uid
|
|
2589
|
+
assert releases[0].revision_retention_count == 3
|
|
2590
|
+
assert releases[0].active_revision is None
|
|
2591
|
+
assert releases[0].desired_revision == desired_revision_uid
|
|
2550
2592
|
|
|
2551
2593
|
|
|
2552
2594
|
def test_legacy_resource_release_deployment_run_model_is_not_exported():
|
|
@@ -2582,6 +2624,9 @@ def test_resource_release_create_sends_automatic_deployment(monkeypatch):
|
|
|
2582
2624
|
"tag_regex": "^v[0-9]+\\.[0-9]+\\.[0-9]+$",
|
|
2583
2625
|
"policy_revision": 1,
|
|
2584
2626
|
},
|
|
2627
|
+
"revision_retention_count": 5,
|
|
2628
|
+
"active_revision": "19128ab6-d72f-460c-8525-d758fa92676a",
|
|
2629
|
+
"desired_revision": "2a9370a7-c07f-439c-bcd9-629e3e916699",
|
|
2585
2630
|
}
|
|
2586
2631
|
|
|
2587
2632
|
def _fake_make_request(*, s, loaders, r_type, url, payload, time_out=None):
|
|
@@ -2600,6 +2645,7 @@ def test_resource_release_create_sends_automatic_deployment(monkeypatch):
|
|
|
2600
2645
|
cpu_request="500m",
|
|
2601
2646
|
memory_request="1Gi",
|
|
2602
2647
|
automatic_deployment=True,
|
|
2648
|
+
revision_retention_count=5,
|
|
2603
2649
|
timeout=11,
|
|
2604
2650
|
)
|
|
2605
2651
|
|
|
@@ -2607,14 +2653,42 @@ def test_resource_release_create_sends_automatic_deployment(monkeypatch):
|
|
|
2607
2653
|
assert release.automatic_redeployment_policy is not None
|
|
2608
2654
|
assert release.automatic_redeployment_policy.tag_regex == "^v[0-9]+\\.[0-9]+\\.[0-9]+$"
|
|
2609
2655
|
assert release.automatic_redeployment_policy.policy_revision == 1
|
|
2656
|
+
assert release.revision_retention_count == 5
|
|
2657
|
+
assert release.active_revision == "19128ab6-d72f-460c-8525-d758fa92676a"
|
|
2658
|
+
assert release.desired_revision == "2a9370a7-c07f-439c-bcd9-629e3e916699"
|
|
2610
2659
|
assert captured["r_type"] == "POST"
|
|
2611
2660
|
assert str(captured["url"]).endswith("/api/v1/resource-releases/")
|
|
2612
2661
|
assert captured["payload"]["json"]["automatic_deployment"] is True
|
|
2662
|
+
assert captured["payload"]["json"]["revision_retention_count"] == 5
|
|
2613
2663
|
assert captured["payload"]["json"]["resource_uid"] == resource_uid
|
|
2614
2664
|
assert captured["payload"]["json"]["related_image_uid"] == image_uid
|
|
2615
2665
|
assert captured["timeout"] == 11
|
|
2616
2666
|
|
|
2617
2667
|
|
|
2668
|
+
@pytest.mark.parametrize("invalid_value", [0, -1, True, 1.5, "3"])
|
|
2669
|
+
def test_resource_release_create_rejects_invalid_revision_retention_count(
|
|
2670
|
+
monkeypatch, invalid_value
|
|
2671
|
+
):
|
|
2672
|
+
monkeypatch.setattr(
|
|
2673
|
+
models_helpers_mod,
|
|
2674
|
+
"make_request",
|
|
2675
|
+
lambda **kwargs: pytest.fail("invalid retention must fail before the request"),
|
|
2676
|
+
)
|
|
2677
|
+
|
|
2678
|
+
with pytest.raises(
|
|
2679
|
+
ValueError,
|
|
2680
|
+
match="revision_retention_count must be a positive integer",
|
|
2681
|
+
):
|
|
2682
|
+
models_helpers_mod.ResourceRelease.create(
|
|
2683
|
+
resource_uid="857bec7b-dd77-4272-aecd-13fc2138eacc",
|
|
2684
|
+
related_image_uid="6cfdb152-923e-45b9-a150-c4541c68b0d1",
|
|
2685
|
+
release_kind=models_helpers_mod.ResourceReleaseKind.FAST_API,
|
|
2686
|
+
cpu_request="500m",
|
|
2687
|
+
memory_request="1Gi",
|
|
2688
|
+
revision_retention_count=invalid_value,
|
|
2689
|
+
)
|
|
2690
|
+
|
|
2691
|
+
|
|
2618
2692
|
def test_project_resource_create_release_uses_related_image_uid(monkeypatch):
|
|
2619
2693
|
captured = {}
|
|
2620
2694
|
resource_uid = "857bec7b-dd77-4272-aecd-13fc2138eacc"
|
|
@@ -2703,6 +2777,9 @@ def test_resource_release_get_accepts_fastapi_cors_allowed_origins(monkeypatch):
|
|
|
2703
2777
|
"release_kind": "fastapi",
|
|
2704
2778
|
"automatic_deployment": True,
|
|
2705
2779
|
"automatic_redeployment_policy": None,
|
|
2780
|
+
"revision_retention_count": 4,
|
|
2781
|
+
"active_revision": "19128ab6-d72f-460c-8525-d758fa92676a",
|
|
2782
|
+
"desired_revision": None,
|
|
2706
2783
|
"cors_allowed_origins": [
|
|
2707
2784
|
"https://app.example.com",
|
|
2708
2785
|
"https://*.site-dev.main-sequence.app",
|
|
@@ -2732,12 +2809,70 @@ def test_resource_release_get_accepts_fastapi_cors_allowed_origins(monkeypatch):
|
|
|
2732
2809
|
release = models_helpers_mod.ResourceRelease.get(pk=release_uid, timeout=13)
|
|
2733
2810
|
|
|
2734
2811
|
assert release.release_kind == models_helpers_mod.ResourceReleaseKind.FAST_API
|
|
2812
|
+
assert release.revision_retention_count == 4
|
|
2813
|
+
assert release.active_revision == "19128ab6-d72f-460c-8525-d758fa92676a"
|
|
2814
|
+
assert release.desired_revision is None
|
|
2735
2815
|
assert release.cors_allowed_origins == response_payload["cors_allowed_origins"]
|
|
2736
2816
|
assert captured["r_type"] == "GET"
|
|
2737
2817
|
assert captured["url"].endswith(f"/resource-releases/{release_uid}/")
|
|
2738
2818
|
assert captured["timeout"] == 13
|
|
2739
2819
|
|
|
2740
2820
|
|
|
2821
|
+
def test_resource_release_patch_supports_positive_revision_retention_count(monkeypatch):
|
|
2822
|
+
captured = {}
|
|
2823
|
+
release_uid = "2f4c4c3d-5669-4da5-9d86-b84633c1e6ed"
|
|
2824
|
+
release = models_helpers_mod.ResourceRelease(
|
|
2825
|
+
uid=release_uid,
|
|
2826
|
+
release_kind="fastapi",
|
|
2827
|
+
revision_retention_count=3,
|
|
2828
|
+
)
|
|
2829
|
+
|
|
2830
|
+
class FakeResponse:
|
|
2831
|
+
status_code = 200
|
|
2832
|
+
|
|
2833
|
+
@staticmethod
|
|
2834
|
+
def json():
|
|
2835
|
+
return {
|
|
2836
|
+
"revision_retention_count": 6,
|
|
2837
|
+
"active_revision": None,
|
|
2838
|
+
"desired_revision": None,
|
|
2839
|
+
}
|
|
2840
|
+
|
|
2841
|
+
def _fake_make_request(*, s, loaders, r_type, url, payload, time_out=None):
|
|
2842
|
+
captured.update({"r_type": r_type, "url": url, "payload": payload})
|
|
2843
|
+
return FakeResponse()
|
|
2844
|
+
|
|
2845
|
+
monkeypatch.setattr(base_mod, "make_request", _fake_make_request)
|
|
2846
|
+
|
|
2847
|
+
patched = release.patch(revision_retention_count=6)
|
|
2848
|
+
|
|
2849
|
+
assert patched is release
|
|
2850
|
+
assert patched.revision_retention_count == 6
|
|
2851
|
+
assert captured["r_type"] == "PATCH"
|
|
2852
|
+
assert captured["url"].endswith(f"/resource-releases/{release_uid}/")
|
|
2853
|
+
assert captured["payload"]["json"] == {"revision_retention_count": 6}
|
|
2854
|
+
|
|
2855
|
+
|
|
2856
|
+
@pytest.mark.parametrize("invalid_value", [None, 0, -1, True, 1.5, "3"])
|
|
2857
|
+
def test_resource_release_patch_rejects_invalid_revision_retention_count(
|
|
2858
|
+
monkeypatch, invalid_value
|
|
2859
|
+
):
|
|
2860
|
+
monkeypatch.setattr(
|
|
2861
|
+
base_mod,
|
|
2862
|
+
"make_request",
|
|
2863
|
+
lambda **kwargs: pytest.fail("invalid retention must fail before the request"),
|
|
2864
|
+
)
|
|
2865
|
+
|
|
2866
|
+
with pytest.raises(
|
|
2867
|
+
ValueError,
|
|
2868
|
+
match="revision_retention_count must be a positive integer",
|
|
2869
|
+
):
|
|
2870
|
+
models_helpers_mod.ResourceRelease.patch_by_uid(
|
|
2871
|
+
"2f4c4c3d-5669-4da5-9d86-b84633c1e6ed",
|
|
2872
|
+
revision_retention_count=invalid_value,
|
|
2873
|
+
)
|
|
2874
|
+
|
|
2875
|
+
|
|
2741
2876
|
def _resource_release_pipeline_payload(*, running_step: str | None = None):
|
|
2742
2877
|
keys = (
|
|
2743
2878
|
"resolve_revision",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-6.0.48 → mainsequence-6.0.49}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
{mainsequence-6.0.48 → mainsequence-6.0.49}/agent_scaffold/skills/data_access/exploration/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-6.0.48 → mainsequence-6.0.49}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-6.0.48 → mainsequence-6.0.49}/agent_scaffold/skills/sdk_project_execution/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/data_sources_interfaces/__init__.py
RENAMED
|
File without changes
|
{mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/data_sources_interfaces/duckdb.py
RENAMED
|
File without changes
|
|
File without changes
|
{mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/client/data_sources_interfaces/sqlite.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/compiled_sql/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/data_nodes/build_operations.py
RENAMED
|
File without changes
|
{mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/data_nodes/data_nodes.py
RENAMED
|
File without changes
|
|
File without changes
|
{mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/data_nodes/namespacing.py
RENAMED
|
File without changes
|
{mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/data_nodes/persist_managers.py
RENAMED
|
File without changes
|
{mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/data_nodes/run_operations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-6.0.48 → mainsequence-6.0.49}/mainsequence/meta_tables/sqlalchemy_contracts.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-6.0.48 → mainsequence-6.0.49}/tests/test_data_node_storage_dimension_queries.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|