mainsequence 8.1.21.dev20__tar.gz → 8.1.22.dev21__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-8.1.21.dev20/mainsequence.egg-info → mainsequence-8.1.22.dev21}/PKG-INFO +1 -1
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +10 -10
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +34 -100
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/cli/api.py +0 -368
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/cli/cli.py +0 -1227
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/base.py +5 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/models_foundry.py +3 -71
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/models_helpers.py +4 -544
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21/mainsequence.egg-info}/PKG-INFO +1 -1
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/pyproject.toml +1 -1
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_cli.py +9 -1024
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_code_repository_batch_jobs_from_file.py +1 -18
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_filter_normalization.py +23 -309
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_tolerant_value_sets.py +1 -26
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/LICENSE +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/MANIFEST.in +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/README.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/agent_scaffold/AGENTS.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/agent_scaffold/skills/data_publishing/time_index_table_updates/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/agent_scaffold/skills/maintenance/code_repository_maintenance/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/agent_scaffold/skills/sdk_code_repository_execution/SKILL.md +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/__main__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/bootstrap.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/cli/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/cli/browser_auth.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/cli/code_repository_status.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/cli/config.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/cli/docker_utils.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/cli/doctor.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/cli/local_ops.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/cli/migrations.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/cli/model_filters.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/cli/pydantic_cli.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/cli/sdk_utils.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/cli/ssh_utils.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/cli/ui.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/agent_runtime_models.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/client.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/compute_validation.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/dtype_codec.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/exceptions.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/github_issues.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/metatables/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/metatables/core.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/models_user.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/observability.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/utils.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/client/value_sets.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/code_repository_context.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/code_repository_skills.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/defaults.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/instrumentation/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/instrumentation/utils.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/logconf.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/__main__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/future_registry.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/hashing.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/migrations/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/migrations/alembic.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/migrations/env.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/migrations/provider.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/migrations/registry.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/schema_names.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/time_index_table_refs.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/time_index_table_updates/__init__.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/time_index_table_updates/configuration.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/time_index_table_updates/dependencies.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/time_index_table_updates/managers.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/time_index_table_updates/namespacing.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/time_index_table_updates/runner.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/time_index_table_updates/updaters.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/meta_tables/time_index_table_updates/utils.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/repository_identity_security.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/runtime_flags.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence/scaffold_skills.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence.egg-info/SOURCES.txt +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence.egg-info/dependency_links.txt +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence.egg-info/entry_points.txt +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence.egg-info/requires.txt +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/mainsequence.egg-info/top_level.txt +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/setup.cfg +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/fixtures/time_index_table_update_hash_v2_golden.json +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_auth_precedence.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_canonical_api_route_contract.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_cli_browser_auth.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_cli_migrations.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_client.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_code_repository_branch_contract.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_code_repository_documentation_contract.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_code_repository_runtime_context.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_code_repository_skills.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_dependency_extras.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_dev_release_version.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_duckdb_interface_dimensions.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_environment_resource_context.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_environment_response_contracts.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_github_issues_client.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_instrumentation.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_local_ops.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_logconf.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_meta_table_migrations.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_meta_tables_client_models.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_models_user_request_bound_auth.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_notification_uid_contract.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_observability_client.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_pod_project_resolution.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_scaffold_skills.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_schema_names.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_secret_client_model.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_source_table_configuration.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_sqlite_interface_dimensions.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_ssh_utils.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_time_index_table_access_dimension_audit.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_time_index_table_dimension_queries.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_time_index_table_update_configuration.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_time_index_table_update_configuration_client.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_time_index_table_update_flow.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_time_index_table_update_hard_cut.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_tolerant_response_reading.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_update_runner_uid_runtime.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_update_statistics.py +0 -0
- {mainsequence-8.1.21.dev20 → mainsequence-8.1.22.dev21}/tests/test_update_uid_guards.py +0 -0
|
@@ -187,27 +187,27 @@ Before release, verify local CodeRepository resolution:
|
|
|
187
187
|
mainsequence code-repository current --debug --json
|
|
188
188
|
```
|
|
189
189
|
|
|
190
|
-
|
|
190
|
+
Declare the FastAPI resource in `.mainsequence/workflows/`, validate the
|
|
191
|
+
workflow against the backend template, then move the tested commit through the
|
|
192
|
+
canonical lifecycle:
|
|
191
193
|
|
|
192
194
|
```bash
|
|
193
195
|
mainsequence code-repository sync -m "Release Command Center API"
|
|
194
|
-
mainsequence code-repository images create
|
|
195
196
|
mainsequence code-repository resources list --filter resource_type=fastapi
|
|
196
|
-
mainsequence code-repository resources create_fastapi
|
|
197
197
|
```
|
|
198
198
|
|
|
199
199
|
Verify that:
|
|
200
200
|
|
|
201
201
|
- code-repository sync used the intended Git branch
|
|
202
|
-
- the
|
|
203
|
-
- resource discovery found
|
|
204
|
-
-
|
|
205
|
-
- the
|
|
202
|
+
- the workflow declaration identifies the tested FastAPI source path
|
|
203
|
+
- resource discovery found that path at the exact deployed commit
|
|
204
|
+
- Django resolved and built the exact image for the workflow event
|
|
205
|
+
- the resulting release kind is `fastapi`
|
|
206
206
|
- compute and spot settings are intentional
|
|
207
207
|
|
|
208
|
-
|
|
209
|
-
frontend contracts are stable
|
|
210
|
-
|
|
208
|
+
Enable automatic deployment in the repository workflow when the route paths,
|
|
209
|
+
resource path, and frontend contracts are stable enough for future repository
|
|
210
|
+
events to promote exact images.
|
|
211
211
|
|
|
212
212
|
### 6. Verify the deployed API
|
|
213
213
|
|
|
@@ -21,17 +21,11 @@ This skill is for:
|
|
|
21
21
|
|
|
22
22
|
## This Skill Can Do
|
|
23
23
|
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
- bind every job to one exact code repository image
|
|
30
|
-
- configure standalone Job automatic deployment as future exact-image promotion
|
|
31
|
-
- inspect job runs and logs
|
|
32
|
-
- reason about code repository resources and resource releases
|
|
33
|
-
- decide whether a `ResourceRelease` should opt into `automatic_deployment`
|
|
34
|
-
- inspect automatic deployment run state for release rotations
|
|
24
|
+
- author and validate Job, FastAPI, and Static Site workflow declarations
|
|
25
|
+
- inspect exact CodeRepository images, Jobs, ResourceReleases, and deployment runs
|
|
26
|
+
- run an existing Job manually and inspect logs
|
|
27
|
+
- update supported properties on an existing Job or release
|
|
28
|
+
- reason about automatic deployment and repository-event image promotion
|
|
35
29
|
- review Artifact-based workflows in operational pipelines
|
|
36
30
|
|
|
37
31
|
## This Skill Must Not Claim
|
|
@@ -68,41 +62,19 @@ changing the operational workflow.
|
|
|
68
62
|
|
|
69
63
|
## Inputs This Skill Needs
|
|
70
64
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
- whether the job is:
|
|
77
|
-
- manual
|
|
78
|
-
- interval
|
|
79
|
-
- crontab
|
|
80
|
-
- one-off
|
|
81
|
-
- the image strategy:
|
|
82
|
-
- existing image
|
|
83
|
-
- new image
|
|
84
|
-
- whether the workflow is:
|
|
85
|
-
- direct CLI/client job creation
|
|
86
|
-
- backend-managed code-repository workflow declarations
|
|
87
|
-
- whether a `ResourceRelease` should be manually pinned or opted into repository-sync automatic deployment
|
|
88
|
-
- whether Artifact inputs or outputs are part of the run
|
|
89
|
-
- who owns the exact initial image: the caller for manual pinning or the
|
|
90
|
-
backend for automatic deployment
|
|
91
|
-
- whether future qualifying immutable repository events may promote a standalone Job
|
|
92
|
-
|
|
93
|
-
If the execution target or image strategy is unclear, stop before scheduling anything.
|
|
65
|
+
Identify the repository source path or Job execution path, the product kind,
|
|
66
|
+
schedule and compute intent, and whether future qualifying repository events
|
|
67
|
+
should promote the target. For an existing target, obtain its public UID before
|
|
68
|
+
running or updating it. The repository workflow is the creation input; callers
|
|
69
|
+
do not select image, resource, Job, or release UIDs for creation.
|
|
94
70
|
|
|
95
71
|
## Required Decisions
|
|
96
72
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
automatic deployment make the backend derive it from the synchronized commit?
|
|
103
|
-
4. Does the workflow depend on Artifacts?
|
|
104
|
-
5. Is the task actually a release/resource problem instead of only a job problem?
|
|
105
|
-
6. For a `ResourceRelease`, should repository sync be allowed to rotate the release automatically through `automatic_deployment`?
|
|
73
|
+
1. Which repository workflow declaration owns the target?
|
|
74
|
+
2. Is the Job manual, interval, crontab, or one-off?
|
|
75
|
+
3. Should future exact repository events promote its image automatically?
|
|
76
|
+
4. Are Artifacts inputs or outputs of the run?
|
|
77
|
+
5. Which existing Job or release needs observation or an explicit operation?
|
|
106
78
|
|
|
107
79
|
## Build Rules
|
|
108
80
|
|
|
@@ -129,38 +101,11 @@ Do not hide important recurring schedules in ad hoc shell history or one-off man
|
|
|
129
101
|
|
|
130
102
|
### 2. Every Job requires one exact image
|
|
131
103
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
- images are built from pushed commits
|
|
138
|
-
- if a commit is not on the remote, it cannot be used for an image
|
|
139
|
-
- there is no dynamic, blank-image, branch-tip, or `latest` Job mode
|
|
140
|
-
- a manual Job requires the caller to select `related_image_uid`
|
|
141
|
-
- an automatic Job forbids caller image selection; the backend derives the
|
|
142
|
-
exact initial image from the CodeRepositoryBranch's persisted synchronized commit
|
|
143
|
-
|
|
144
|
-
When standalone Job automatic deployment is enabled during creation, the
|
|
145
|
-
backend prepares the exact initial image and later qualifying immutable
|
|
146
|
-
repository events may atomically promote another exact image. On an existing
|
|
147
|
-
Job, enabling or disabling it retains the current exact image. The backend owns
|
|
148
|
-
repository-event truth, policy evaluation, image preparation, and promotion;
|
|
149
|
-
CodeRepository code and the SDK must not choose a Job's deployment branch or image.
|
|
150
|
-
This deployment-policy rule does not replace ADR-0037 runtime source discovery:
|
|
151
|
-
code executing inside the resulting code repository image still resolves and validates
|
|
152
|
-
its attached Git branch and exact commit.
|
|
153
|
-
|
|
154
|
-
For direct creation use:
|
|
155
|
-
|
|
156
|
-
- `--automatic-deployment` to permit future exact-image promotion
|
|
157
|
-
- `--no-automatic-deployment` to keep future repository events from changing
|
|
158
|
-
the Job image
|
|
159
|
-
- `--automatic-redeployment-tag-regex` to require a full matching immutable
|
|
160
|
-
tag; omit the regex for every otherwise-eligible exact event
|
|
161
|
-
|
|
162
|
-
Use `--related-image-uid` only for manual pinning. Omit it with
|
|
163
|
-
`--automatic-deployment`; passing both is invalid.
|
|
104
|
+
Django derives the initial image from the exact repository event when it
|
|
105
|
+
applies a `kind: job` workflow declaration. A later qualifying event may
|
|
106
|
+
promote another exact image under the Job's automatic deployment policy.
|
|
107
|
+
There is no dynamic, blank-image, branch-tip, or `latest` execution mode.
|
|
108
|
+
A caller does not create an image or Job by selecting a stored image UID.
|
|
164
109
|
|
|
165
110
|
### 3. Jobs must be verifiable after creation
|
|
166
111
|
|
|
@@ -201,7 +146,7 @@ Current support matrix:
|
|
|
201
146
|
| `Job.run_job(command_args=[...])` | Supported for that manual run |
|
|
202
147
|
| `mainsequence code-repository jobs run ... --arg/-- ...` | Supported for that manual run |
|
|
203
148
|
| `Job.scheduled_command_args` | Persisted list copied into future scheduler-created runs |
|
|
204
|
-
| `mainsequence code-repository jobs
|
|
149
|
+
| `mainsequence code-repository jobs update --scheduled-arg ...` | Replaces the persisted list on an existing Job |
|
|
205
150
|
| `.mainsequence/workflows/*.yaml` Job declaration | Supports `scheduled_command_args` as an ordered `list[str]` |
|
|
206
151
|
|
|
207
152
|
Keep `scheduled_command_args` separate from manual `command_args`. Retrieve the
|
|
@@ -298,36 +243,27 @@ Enable `automatic_deployment` only when:
|
|
|
298
243
|
|
|
299
244
|
Keep `automatic_deployment` disabled when:
|
|
300
245
|
|
|
301
|
-
- the release
|
|
246
|
+
- the release should not promote on future repository events
|
|
302
247
|
- each release rotation needs human approval
|
|
303
248
|
- the resource path or entrypoint is still moving
|
|
304
249
|
- API or widget contracts are not stable enough for automatic rotation
|
|
305
250
|
- the current branch/CodeRepository sync target is not the intended deployment source
|
|
306
251
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
The SDK surface also accepts:
|
|
313
|
-
|
|
314
|
-
- `CodeRepositoryResource.create_fastapi(..., automatic_deployment=True)`
|
|
315
|
-
- `ResourceRelease.create(..., automatic_deployment=True)`
|
|
316
|
-
- `ResourceRelease.deploy_current_version()` for an SDK-triggered manual deployment run; it returns `DeploymentRun`
|
|
317
|
-
- `DeploymentRun.filter(target_type="resource_release", target_uid=release.uid)` to inspect runs for one release
|
|
252
|
+
Declare opted-in releases in the repository workflow and validate the file
|
|
253
|
+
against the backend template. Repository events create deployment runs.
|
|
254
|
+
`DeploymentRun.filter(target_type="resource_release", target_uid=release.uid)`
|
|
255
|
+
inspects runs for an existing release.
|
|
318
256
|
|
|
319
257
|
Every release also exposes its immutable revision lifecycle:
|
|
320
258
|
|
|
321
259
|
- `desired_revision` is the public UID of the accepted revision being materialized
|
|
322
260
|
- `active_revision` is the public UID of the ready revision currently serving behind the stable release URL
|
|
323
261
|
- the two UIDs may differ while a deployment is running or after a deployment fails
|
|
324
|
-
- `revision_retention_count` is the positive release-owned retention setting; omission
|
|
325
|
-
- configure retention
|
|
262
|
+
- `revision_retention_count` is the positive release-owned retention setting; omission in the workflow uses the backend default
|
|
263
|
+
- configure retention in the workflow or update an existing release with `release.patch(revision_retention_count=5)`
|
|
326
264
|
|
|
327
265
|
Treat `active_revision` and `desired_revision` as read-only public identities. Do not substitute provider revision names, deployment names, or internal database IDs.
|
|
328
266
|
|
|
329
|
-
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.
|
|
330
|
-
|
|
331
267
|
Inspect the unified run's `state`, `phase`, `outcome`, `steps`, `logs`, and `error` fields. Do not use legacy resource-release deployment status fields or filters.
|
|
332
268
|
Detail responses also expose `builder_image` and `builder_runtime`; these are empty strings when the run has no static-site builder metadata.
|
|
333
269
|
|
|
@@ -336,11 +272,9 @@ Detail responses also expose `builder_image` and `builder_runtime`; these are em
|
|
|
336
272
|
When reviewing an orchestration task, look for:
|
|
337
273
|
|
|
338
274
|
- schedules that should have been version-controlled
|
|
339
|
-
-
|
|
340
|
-
-
|
|
341
|
-
- jobs tied to moving repository state instead of
|
|
342
|
-
- manual Job creation that omits an exact ready image
|
|
343
|
-
- automatic Job creation that supplies a caller-selected image
|
|
275
|
+
- a missing repository workflow declaration for a new Job
|
|
276
|
+
- a workflow with a caller-selected image or generated platform UID
|
|
277
|
+
- jobs tied to moving repository state instead of an exact image
|
|
344
278
|
- client code that interprets automatic deployment as a branch-tip or `latest` selector
|
|
345
279
|
- no run/log verification after creation
|
|
346
280
|
- unsafe use of `--strict`
|
|
@@ -360,9 +294,9 @@ Do not claim success until you have checked:
|
|
|
360
294
|
- interval
|
|
361
295
|
- crontab
|
|
362
296
|
- one-off
|
|
363
|
-
-
|
|
297
|
+
- the exact repository event and backend-owned image preparation are intentional
|
|
364
298
|
- standalone Job automatic deployment and tag policy are intentionally enabled or disabled
|
|
365
|
-
- the
|
|
299
|
+
- the Job exists after repository workflow application
|
|
366
300
|
- runs and logs were inspected when execution success matters
|
|
367
301
|
- resources and releases were verified when deployment success matters
|
|
368
302
|
- `automatic_deployment` is intentionally enabled or disabled on each release
|
|
@@ -386,7 +320,7 @@ If the workflow uses Artifacts, also check:
|
|
|
386
320
|
- the execution target is unclear
|
|
387
321
|
- the image strategy is unclear but reproducibility matters
|
|
388
322
|
- the backend rejects the workflow version, resource kind, or requested field
|
|
389
|
-
- a
|
|
323
|
+
- a Job workflow cannot resolve an exact source image
|
|
390
324
|
- an automatically deployed Job has no persisted synchronized CodeRepositoryBranch commit
|
|
391
325
|
- the workflow depends on local file paths that should be platform Artifacts
|
|
392
326
|
- automatic deployment is requested but the deployment source branch/current synced CodeRepository version is unclear
|
|
@@ -2171,117 +2171,6 @@ def get_code_repository_time_index_table_updates(
|
|
|
2171
2171
|
os.environ[k] = v
|
|
2172
2172
|
|
|
2173
2173
|
|
|
2174
|
-
def create_code_repository_image(
|
|
2175
|
-
*,
|
|
2176
|
-
code_repository_commit_hash: str,
|
|
2177
|
-
related_code_repository_branch_uid: str,
|
|
2178
|
-
base_image_uid: str | None = None,
|
|
2179
|
-
timeout: int | None = None,
|
|
2180
|
-
) -> dict[str, Any]:
|
|
2181
|
-
"""
|
|
2182
|
-
Create a code repository image via SDK client model.
|
|
2183
|
-
|
|
2184
|
-
Single source of truth:
|
|
2185
|
-
- delegates payload construction and request behavior to `CodeRepositoryImage.create()`
|
|
2186
|
-
- avoids duplicating the endpoint contract in the CLI API wrapper
|
|
2187
|
-
"""
|
|
2188
|
-
tokens = get_tokens()
|
|
2189
|
-
access = (tokens.get("access") or "").strip()
|
|
2190
|
-
refresh = (tokens.get("refresh") or "").strip()
|
|
2191
|
-
if not access:
|
|
2192
|
-
raise NotLoggedIn("Not logged in.")
|
|
2193
|
-
|
|
2194
|
-
endpoint = backend_url().rstrip("/")
|
|
2195
|
-
root_url = f"{endpoint}/api/v1"
|
|
2196
|
-
|
|
2197
|
-
old_env = {
|
|
2198
|
-
"MAINSEQUENCE_AUTH_MODE": os.environ.get("MAINSEQUENCE_AUTH_MODE"),
|
|
2199
|
-
"MAINSEQUENCE_ACCESS_TOKEN": os.environ.get("MAINSEQUENCE_ACCESS_TOKEN"),
|
|
2200
|
-
"MAINSEQUENCE_REFRESH_TOKEN": os.environ.get("MAINSEQUENCE_REFRESH_TOKEN"),
|
|
2201
|
-
"MAINSEQUENCE_ENDPOINT": os.environ.get("MAINSEQUENCE_ENDPOINT"),
|
|
2202
|
-
}
|
|
2203
|
-
|
|
2204
|
-
client_utils = None
|
|
2205
|
-
old_provider = None
|
|
2206
|
-
old_base_root_url = None
|
|
2207
|
-
old_image_root_url = None
|
|
2208
|
-
|
|
2209
|
-
try:
|
|
2210
|
-
os.environ["MAINSEQUENCE_AUTH_MODE"] = "jwt"
|
|
2211
|
-
os.environ["MAINSEQUENCE_ACCESS_TOKEN"] = access
|
|
2212
|
-
if refresh:
|
|
2213
|
-
os.environ["MAINSEQUENCE_REFRESH_TOKEN"] = refresh
|
|
2214
|
-
else:
|
|
2215
|
-
os.environ.pop("MAINSEQUENCE_REFRESH_TOKEN", None)
|
|
2216
|
-
os.environ["MAINSEQUENCE_ENDPOINT"] = endpoint
|
|
2217
|
-
resolved_branch_uid = resolve_code_repository_branch_uid(related_code_repository_branch_uid)
|
|
2218
|
-
|
|
2219
|
-
from mainsequence.client import utils as _client_utils
|
|
2220
|
-
from mainsequence.client.base import BaseObjectOrm
|
|
2221
|
-
from mainsequence.client.models_foundry import (
|
|
2222
|
-
CodeRepositoryImage as ClientCodeRepositoryImage,
|
|
2223
|
-
)
|
|
2224
|
-
|
|
2225
|
-
client_utils = _client_utils
|
|
2226
|
-
old_provider = getattr(client_utils.loaders, "provider", None)
|
|
2227
|
-
old_base_root_url = BaseObjectOrm.ROOT_URL
|
|
2228
|
-
old_image_root_url = getattr(ClientCodeRepositoryImage, "ROOT_URL", None)
|
|
2229
|
-
|
|
2230
|
-
_set_client_utils_endpoint(client_utils, endpoint)
|
|
2231
|
-
client_utils.loaders.use_jwt(access=access, refresh=refresh or None)
|
|
2232
|
-
|
|
2233
|
-
BaseObjectOrm.ROOT_URL = root_url
|
|
2234
|
-
ClientCodeRepositoryImage.ROOT_URL = root_url
|
|
2235
|
-
|
|
2236
|
-
created = ClientCodeRepositoryImage.create(
|
|
2237
|
-
code_repository_commit_hash=code_repository_commit_hash,
|
|
2238
|
-
related_code_repository_branch_uid=resolved_branch_uid,
|
|
2239
|
-
base_image_uid=base_image_uid,
|
|
2240
|
-
timeout=timeout,
|
|
2241
|
-
)
|
|
2242
|
-
if isinstance(created, dict):
|
|
2243
|
-
return created
|
|
2244
|
-
if hasattr(created, "model_dump"):
|
|
2245
|
-
return created.model_dump()
|
|
2246
|
-
return {"uid": getattr(created, "uid", None)}
|
|
2247
|
-
|
|
2248
|
-
except Exception as e:
|
|
2249
|
-
err_name = type(e).__name__
|
|
2250
|
-
if err_name in {"AuthenticationError", "PermissionDeniedError"}:
|
|
2251
|
-
raise NotLoggedIn(str(e) or "Not logged in.") from e
|
|
2252
|
-
if err_name == "NotFoundError":
|
|
2253
|
-
raise ApiError(
|
|
2254
|
-
f"CodeRepositoryBranch not found: {related_code_repository_branch_uid}"
|
|
2255
|
-
) from e
|
|
2256
|
-
raise ApiError(f"CodeRepository image create failed: {e}") from e
|
|
2257
|
-
finally:
|
|
2258
|
-
if client_utils is not None:
|
|
2259
|
-
try:
|
|
2260
|
-
client_utils.loaders.provider = old_provider
|
|
2261
|
-
except Exception:
|
|
2262
|
-
pass
|
|
2263
|
-
if old_base_root_url is not None:
|
|
2264
|
-
try:
|
|
2265
|
-
from mainsequence.client.base import BaseObjectOrm
|
|
2266
|
-
|
|
2267
|
-
BaseObjectOrm.ROOT_URL = old_base_root_url
|
|
2268
|
-
except Exception:
|
|
2269
|
-
pass
|
|
2270
|
-
if old_image_root_url is not None:
|
|
2271
|
-
try:
|
|
2272
|
-
from mainsequence.client.models_foundry import (
|
|
2273
|
-
CodeRepositoryImage as ClientCodeRepositoryImage,
|
|
2274
|
-
)
|
|
2275
|
-
|
|
2276
|
-
ClientCodeRepositoryImage.ROOT_URL = old_image_root_url
|
|
2277
|
-
except Exception:
|
|
2278
|
-
pass
|
|
2279
|
-
|
|
2280
|
-
for k, v in old_env.items():
|
|
2281
|
-
if v is None:
|
|
2282
|
-
os.environ.pop(k, None)
|
|
2283
|
-
else:
|
|
2284
|
-
os.environ[k] = v
|
|
2285
2174
|
|
|
2286
2175
|
|
|
2287
2176
|
def list_code_repository_images(
|
|
@@ -2797,135 +2686,6 @@ def list_code_repository_resources(
|
|
|
2797
2686
|
os.environ[k] = v
|
|
2798
2687
|
|
|
2799
2688
|
|
|
2800
|
-
def create_code_repository_resource_release(
|
|
2801
|
-
*,
|
|
2802
|
-
release_kind: str,
|
|
2803
|
-
resource_uid: str,
|
|
2804
|
-
related_image_uid: str | None = None,
|
|
2805
|
-
cpu_request: str | int | float | None = None,
|
|
2806
|
-
memory_request: str | int | float | None = None,
|
|
2807
|
-
gpu_request: str | int | None = None,
|
|
2808
|
-
gpu_type: str | None = None,
|
|
2809
|
-
spot: bool | None = None,
|
|
2810
|
-
automatic_deployment: bool | None = None,
|
|
2811
|
-
timeout: int | None = None,
|
|
2812
|
-
) -> dict[str, Any]:
|
|
2813
|
-
"""
|
|
2814
|
-
Create a resource release via SDK client model.
|
|
2815
|
-
|
|
2816
|
-
Single source of truth:
|
|
2817
|
-
- delegates to `CodeRepositoryResource.create_fastapi()`
|
|
2818
|
-
- which in turn use `ResourceRelease.create()`
|
|
2819
|
-
"""
|
|
2820
|
-
normalized_release_kind = str(release_kind).strip()
|
|
2821
|
-
if normalized_release_kind != "fastapi":
|
|
2822
|
-
raise ApiError("release_kind must be 'fastapi'.")
|
|
2823
|
-
|
|
2824
|
-
tokens = get_tokens()
|
|
2825
|
-
access = (tokens.get("access") or "").strip()
|
|
2826
|
-
refresh = (tokens.get("refresh") or "").strip()
|
|
2827
|
-
if not access:
|
|
2828
|
-
raise NotLoggedIn("Not logged in.")
|
|
2829
|
-
|
|
2830
|
-
endpoint = backend_url().rstrip("/")
|
|
2831
|
-
root_url = f"{endpoint}/api/v1"
|
|
2832
|
-
|
|
2833
|
-
old_env = {
|
|
2834
|
-
"MAINSEQUENCE_AUTH_MODE": os.environ.get("MAINSEQUENCE_AUTH_MODE"),
|
|
2835
|
-
"MAINSEQUENCE_ACCESS_TOKEN": os.environ.get("MAINSEQUENCE_ACCESS_TOKEN"),
|
|
2836
|
-
"MAINSEQUENCE_REFRESH_TOKEN": os.environ.get("MAINSEQUENCE_REFRESH_TOKEN"),
|
|
2837
|
-
"MAINSEQUENCE_ENDPOINT": os.environ.get("MAINSEQUENCE_ENDPOINT"),
|
|
2838
|
-
}
|
|
2839
|
-
|
|
2840
|
-
client_utils = None
|
|
2841
|
-
old_provider = None
|
|
2842
|
-
old_base_root_url = None
|
|
2843
|
-
old_resource_root_url = None
|
|
2844
|
-
|
|
2845
|
-
try:
|
|
2846
|
-
os.environ["MAINSEQUENCE_AUTH_MODE"] = "jwt"
|
|
2847
|
-
os.environ["MAINSEQUENCE_ACCESS_TOKEN"] = access
|
|
2848
|
-
if refresh:
|
|
2849
|
-
os.environ["MAINSEQUENCE_REFRESH_TOKEN"] = refresh
|
|
2850
|
-
else:
|
|
2851
|
-
os.environ.pop("MAINSEQUENCE_REFRESH_TOKEN", None)
|
|
2852
|
-
os.environ["MAINSEQUENCE_ENDPOINT"] = endpoint
|
|
2853
|
-
|
|
2854
|
-
from mainsequence.client import utils as _client_utils
|
|
2855
|
-
from mainsequence.client.base import BaseObjectOrm
|
|
2856
|
-
from mainsequence.client.models_helpers import (
|
|
2857
|
-
CodeRepositoryResource as ClientCodeRepositoryResource,
|
|
2858
|
-
)
|
|
2859
|
-
|
|
2860
|
-
client_utils = _client_utils
|
|
2861
|
-
old_provider = getattr(client_utils.loaders, "provider", None)
|
|
2862
|
-
old_base_root_url = BaseObjectOrm.ROOT_URL
|
|
2863
|
-
old_resource_root_url = getattr(ClientCodeRepositoryResource, "ROOT_URL", None)
|
|
2864
|
-
|
|
2865
|
-
_set_client_utils_endpoint(client_utils, endpoint)
|
|
2866
|
-
client_utils.loaders.use_jwt(access=access, refresh=refresh or None)
|
|
2867
|
-
|
|
2868
|
-
BaseObjectOrm.ROOT_URL = root_url
|
|
2869
|
-
ClientCodeRepositoryResource.ROOT_URL = root_url
|
|
2870
|
-
|
|
2871
|
-
resource = ClientCodeRepositoryResource.get(pk=resource_uid, timeout=timeout)
|
|
2872
|
-
create_kwargs: dict[str, Any] = {
|
|
2873
|
-
"related_image_uid": related_image_uid,
|
|
2874
|
-
"cpu_request": cpu_request,
|
|
2875
|
-
"memory_request": memory_request,
|
|
2876
|
-
"gpu_request": gpu_request,
|
|
2877
|
-
"gpu_type": gpu_type,
|
|
2878
|
-
"spot": spot,
|
|
2879
|
-
"automatic_deployment": automatic_deployment,
|
|
2880
|
-
"timeout": timeout,
|
|
2881
|
-
}
|
|
2882
|
-
|
|
2883
|
-
create_method = getattr(resource, "create_fastapi", None)
|
|
2884
|
-
if not callable(create_method):
|
|
2885
|
-
raise ApiError("CodeRepositoryResource does not implement create_fastapi().")
|
|
2886
|
-
created = create_method(**create_kwargs)
|
|
2887
|
-
|
|
2888
|
-
if isinstance(created, dict):
|
|
2889
|
-
return created
|
|
2890
|
-
if hasattr(created, "model_dump"):
|
|
2891
|
-
return created.model_dump()
|
|
2892
|
-
return {"uid": getattr(created, "uid", None)}
|
|
2893
|
-
|
|
2894
|
-
except Exception as e:
|
|
2895
|
-
err_name = type(e).__name__
|
|
2896
|
-
if err_name in {"AuthenticationError", "PermissionDeniedError"}:
|
|
2897
|
-
raise NotLoggedIn(str(e) or "Not logged in.") from e
|
|
2898
|
-
if err_name == "NotFoundError":
|
|
2899
|
-
raise ApiError(f"CodeRepository resource not found: {resource_uid}") from e
|
|
2900
|
-
raise ApiError(f"CodeRepository resource release create failed: {e}") from e
|
|
2901
|
-
finally:
|
|
2902
|
-
if client_utils is not None:
|
|
2903
|
-
try:
|
|
2904
|
-
client_utils.loaders.provider = old_provider
|
|
2905
|
-
except Exception:
|
|
2906
|
-
pass
|
|
2907
|
-
if old_base_root_url is not None:
|
|
2908
|
-
try:
|
|
2909
|
-
from mainsequence.client.base import BaseObjectOrm
|
|
2910
|
-
|
|
2911
|
-
BaseObjectOrm.ROOT_URL = old_base_root_url
|
|
2912
|
-
except Exception:
|
|
2913
|
-
pass
|
|
2914
|
-
if old_resource_root_url is not None:
|
|
2915
|
-
try:
|
|
2916
|
-
from mainsequence.client.models_helpers import (
|
|
2917
|
-
CodeRepositoryResource as ClientCodeRepositoryResource,
|
|
2918
|
-
)
|
|
2919
|
-
|
|
2920
|
-
ClientCodeRepositoryResource.ROOT_URL = old_resource_root_url
|
|
2921
|
-
except Exception:
|
|
2922
|
-
pass
|
|
2923
|
-
|
|
2924
|
-
for k, v in old_env.items():
|
|
2925
|
-
if v is None:
|
|
2926
|
-
os.environ.pop(k, None)
|
|
2927
|
-
else:
|
|
2928
|
-
os.environ[k] = v
|
|
2929
2689
|
|
|
2930
2690
|
|
|
2931
2691
|
def list_time_index_tables(
|
|
@@ -4476,134 +4236,6 @@ def remove_meta_table_labels(
|
|
|
4476
4236
|
)
|
|
4477
4237
|
|
|
4478
4238
|
|
|
4479
|
-
def create_code_repository_job(
|
|
4480
|
-
*,
|
|
4481
|
-
name: str,
|
|
4482
|
-
code_repository_branch_uid: str,
|
|
4483
|
-
execution_path: str | None = None,
|
|
4484
|
-
task_schedule: dict[str, Any] | str | None = None,
|
|
4485
|
-
scheduled_command_args: list[str] | None = None,
|
|
4486
|
-
cpu_request: str | int | float | None = None,
|
|
4487
|
-
memory_request: str | int | float | None = None,
|
|
4488
|
-
gpu_request: str | int | float | None = None,
|
|
4489
|
-
gpu_type: str | None = None,
|
|
4490
|
-
spot: bool | None = None,
|
|
4491
|
-
max_runtime_seconds: int | None = None,
|
|
4492
|
-
related_image_uid: str | None = None,
|
|
4493
|
-
automatic_deployment: bool = False,
|
|
4494
|
-
automatic_redeployment_tag_regex: str | None = None,
|
|
4495
|
-
timeout: int | None = None,
|
|
4496
|
-
) -> dict[str, Any]:
|
|
4497
|
-
"""
|
|
4498
|
-
Create a CodeRepository job via the SDK client model.
|
|
4499
|
-
|
|
4500
|
-
Single source of truth:
|
|
4501
|
-
- delegates payload construction and request behavior to `Job.create()`
|
|
4502
|
-
"""
|
|
4503
|
-
tokens = get_tokens()
|
|
4504
|
-
access = (tokens.get("access") or "").strip()
|
|
4505
|
-
refresh = (tokens.get("refresh") or "").strip()
|
|
4506
|
-
if not access:
|
|
4507
|
-
raise NotLoggedIn("Not logged in.")
|
|
4508
|
-
|
|
4509
|
-
endpoint = backend_url().rstrip("/")
|
|
4510
|
-
root_url = f"{endpoint}/api/v1"
|
|
4511
|
-
|
|
4512
|
-
old_env = {
|
|
4513
|
-
"MAINSEQUENCE_AUTH_MODE": os.environ.get("MAINSEQUENCE_AUTH_MODE"),
|
|
4514
|
-
"MAINSEQUENCE_ACCESS_TOKEN": os.environ.get("MAINSEQUENCE_ACCESS_TOKEN"),
|
|
4515
|
-
"MAINSEQUENCE_REFRESH_TOKEN": os.environ.get("MAINSEQUENCE_REFRESH_TOKEN"),
|
|
4516
|
-
"MAINSEQUENCE_ENDPOINT": os.environ.get("MAINSEQUENCE_ENDPOINT"),
|
|
4517
|
-
}
|
|
4518
|
-
|
|
4519
|
-
client_utils = None
|
|
4520
|
-
old_provider = None
|
|
4521
|
-
old_base_root_url = None
|
|
4522
|
-
old_job_root_url = None
|
|
4523
|
-
|
|
4524
|
-
try:
|
|
4525
|
-
os.environ["MAINSEQUENCE_AUTH_MODE"] = "jwt"
|
|
4526
|
-
os.environ["MAINSEQUENCE_ACCESS_TOKEN"] = access
|
|
4527
|
-
if refresh:
|
|
4528
|
-
os.environ["MAINSEQUENCE_REFRESH_TOKEN"] = refresh
|
|
4529
|
-
else:
|
|
4530
|
-
os.environ.pop("MAINSEQUENCE_REFRESH_TOKEN", None)
|
|
4531
|
-
os.environ["MAINSEQUENCE_ENDPOINT"] = endpoint
|
|
4532
|
-
resolved_branch_uid = resolve_code_repository_branch_uid(code_repository_branch_uid)
|
|
4533
|
-
|
|
4534
|
-
from mainsequence.client import utils as _client_utils
|
|
4535
|
-
from mainsequence.client.base import BaseObjectOrm
|
|
4536
|
-
from mainsequence.client.models_helpers import Job as ClientJob
|
|
4537
|
-
|
|
4538
|
-
client_utils = _client_utils
|
|
4539
|
-
old_provider = getattr(client_utils.loaders, "provider", None)
|
|
4540
|
-
old_base_root_url = BaseObjectOrm.ROOT_URL
|
|
4541
|
-
old_job_root_url = getattr(ClientJob, "ROOT_URL", None)
|
|
4542
|
-
|
|
4543
|
-
_set_client_utils_endpoint(client_utils, endpoint)
|
|
4544
|
-
client_utils.loaders.use_jwt(access=access, refresh=refresh or None)
|
|
4545
|
-
|
|
4546
|
-
BaseObjectOrm.ROOT_URL = root_url
|
|
4547
|
-
ClientJob.ROOT_URL = root_url
|
|
4548
|
-
|
|
4549
|
-
created = ClientJob.create(
|
|
4550
|
-
name=name,
|
|
4551
|
-
code_repository_branch_uid=resolved_branch_uid,
|
|
4552
|
-
execution_path=execution_path,
|
|
4553
|
-
task_schedule=task_schedule,
|
|
4554
|
-
scheduled_command_args=scheduled_command_args,
|
|
4555
|
-
cpu_request=cpu_request,
|
|
4556
|
-
memory_request=memory_request,
|
|
4557
|
-
gpu_request=gpu_request,
|
|
4558
|
-
gpu_type=gpu_type,
|
|
4559
|
-
spot=spot,
|
|
4560
|
-
max_runtime_seconds=max_runtime_seconds,
|
|
4561
|
-
related_image_uid=related_image_uid,
|
|
4562
|
-
automatic_deployment=automatic_deployment,
|
|
4563
|
-
automatic_redeployment_policy={
|
|
4564
|
-
"tag_regex": automatic_redeployment_tag_regex,
|
|
4565
|
-
},
|
|
4566
|
-
timeout=timeout,
|
|
4567
|
-
)
|
|
4568
|
-
if isinstance(created, dict):
|
|
4569
|
-
return created
|
|
4570
|
-
if hasattr(created, "model_dump"):
|
|
4571
|
-
return created.model_dump()
|
|
4572
|
-
return {"uid": getattr(created, "uid", None)}
|
|
4573
|
-
|
|
4574
|
-
except Exception as e:
|
|
4575
|
-
err_name = type(e).__name__
|
|
4576
|
-
if err_name in {"AuthenticationError", "PermissionDeniedError"}:
|
|
4577
|
-
raise NotLoggedIn(str(e) or "Not logged in.") from e
|
|
4578
|
-
if err_name == "NotFoundError":
|
|
4579
|
-
raise ApiError(f"CodeRepositoryBranch not found: {code_repository_branch_uid}") from e
|
|
4580
|
-
raise ApiError(f"CodeRepository job create failed: {e}") from e
|
|
4581
|
-
finally:
|
|
4582
|
-
if client_utils is not None:
|
|
4583
|
-
try:
|
|
4584
|
-
client_utils.loaders.provider = old_provider
|
|
4585
|
-
except Exception:
|
|
4586
|
-
pass
|
|
4587
|
-
if old_base_root_url is not None:
|
|
4588
|
-
try:
|
|
4589
|
-
from mainsequence.client.base import BaseObjectOrm
|
|
4590
|
-
|
|
4591
|
-
BaseObjectOrm.ROOT_URL = old_base_root_url
|
|
4592
|
-
except Exception:
|
|
4593
|
-
pass
|
|
4594
|
-
if old_job_root_url is not None:
|
|
4595
|
-
try:
|
|
4596
|
-
from mainsequence.client.models_helpers import Job as ClientJob
|
|
4597
|
-
|
|
4598
|
-
ClientJob.ROOT_URL = old_job_root_url
|
|
4599
|
-
except Exception:
|
|
4600
|
-
pass
|
|
4601
|
-
|
|
4602
|
-
for k, v in old_env.items():
|
|
4603
|
-
if v is None:
|
|
4604
|
-
os.environ.pop(k, None)
|
|
4605
|
-
else:
|
|
4606
|
-
os.environ[k] = v
|
|
4607
4239
|
|
|
4608
4240
|
|
|
4609
4241
|
def update_code_repository_job_scheduled_command_args(
|