feat: update automation schema and automation context for the new automate interfaces
This commit is contained in:
Родитель
6469b6f757
Коммит
f27650af3a
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -36,7 +36,7 @@ pylint = "^2.14.4"
|
||||||
mypy = "^0.982"
|
mypy = "^0.982"
|
||||||
pre-commit = "^2.20.0"
|
pre-commit = "^2.20.0"
|
||||||
commitizen = "^2.38.0"
|
commitizen = "^2.38.0"
|
||||||
ruff = "^0.0.187"
|
ruff = "^0.4.4"
|
||||||
types-deprecated = "^1.2.9"
|
types-deprecated = "^1.2.9"
|
||||||
types-ujson = "^5.6.0.0"
|
types-ujson = "^5.6.0.0"
|
||||||
types-requests = "^2.28.11.5"
|
types-requests = "^2.28.11.5"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
"""This module provides an abstraction layer above the Speckle Automate runtime."""
|
"""This module provides an abstraction layer above the Speckle Automate runtime."""
|
||||||
|
|
||||||
import time
|
import time
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
@ -17,6 +18,7 @@ from speckle_automate.schema import (
|
||||||
)
|
)
|
||||||
from specklepy.api import operations
|
from specklepy.api import operations
|
||||||
from specklepy.api.client import SpeckleClient
|
from specklepy.api.client import SpeckleClient
|
||||||
|
from specklepy.core.api.models import Branch
|
||||||
from specklepy.logging.exceptions import SpeckleException
|
from specklepy.logging.exceptions import SpeckleException
|
||||||
from specklepy.objects.base import Base
|
from specklepy.objects.base import Base
|
||||||
from specklepy.transports.memory import MemoryTransport
|
from specklepy.transports.memory import MemoryTransport
|
||||||
|
@ -94,8 +96,10 @@ class AutomationContext:
|
||||||
|
|
||||||
def receive_version(self) -> Base:
|
def receive_version(self) -> Base:
|
||||||
"""Receive the Speckle project version that triggered this automation run."""
|
"""Receive the Speckle project version that triggered this automation run."""
|
||||||
|
# TODO: this is a quick hack to keep implementation consistency. Move to proper receive many versions
|
||||||
|
version_id = self.automation_run_data.triggers[0].payload.version_id
|
||||||
commit = self.speckle_client.commit.get(
|
commit = self.speckle_client.commit.get(
|
||||||
self.automation_run_data.project_id, self.automation_run_data.version_id
|
self.automation_run_data.project_id, version_id
|
||||||
)
|
)
|
||||||
if not commit.referencedObject:
|
if not commit.referencedObject:
|
||||||
raise ValueError("The commit has no referencedObject, cannot receive it.")
|
raise ValueError("The commit has no referencedObject, cannot receive it.")
|
||||||
|
@ -104,7 +108,7 @@ class AutomationContext:
|
||||||
)
|
)
|
||||||
print(
|
print(
|
||||||
f"It took {self.elapsed():.2f} seconds to receive",
|
f"It took {self.elapsed():.2f} seconds to receive",
|
||||||
f" the speckle version {self.automation_run_data.version_id}",
|
f" the speckle version {version_id}",
|
||||||
)
|
)
|
||||||
return base
|
return base
|
||||||
|
|
||||||
|
@ -119,19 +123,27 @@ class AutomationContext:
|
||||||
version_message (str): The message for the new version.
|
version_message (str): The message for the new version.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if model_name == self.automation_run_data.branch_name:
|
|
||||||
raise ValueError(
|
|
||||||
f"The target model: {model_name} cannot match the model"
|
|
||||||
f" that triggered this automation:"
|
|
||||||
f" {self.automation_run_data.model_id} /"
|
|
||||||
f" {self.automation_run_data.branch_name}"
|
|
||||||
)
|
|
||||||
|
|
||||||
branch = self.speckle_client.branch.get(
|
branch = self.speckle_client.branch.get(
|
||||||
self.automation_run_data.project_id, model_name, 1
|
self.automation_run_data.project_id, model_name, 1
|
||||||
)
|
)
|
||||||
# we just check if it exists
|
if isinstance(branch, Branch):
|
||||||
if (not branch) or isinstance(branch, SpeckleException):
|
if not branch.id:
|
||||||
|
raise ValueError("Cannot use the branch without its id")
|
||||||
|
matching_trigger = [
|
||||||
|
t
|
||||||
|
for t in self.automation_run_data.triggers
|
||||||
|
if t.payload.model_id == branch.id
|
||||||
|
]
|
||||||
|
if matching_trigger:
|
||||||
|
raise ValueError(
|
||||||
|
f"The target model: {model_name} cannot match the model"
|
||||||
|
f" that triggered this automation:"
|
||||||
|
f" {matching_trigger[0].payload.model_id}"
|
||||||
|
)
|
||||||
|
model_id = branch.id
|
||||||
|
|
||||||
|
else:
|
||||||
|
# we just check if it exists
|
||||||
branch_create = self.speckle_client.branch.create(
|
branch_create = self.speckle_client.branch.create(
|
||||||
self.automation_run_data.project_id,
|
self.automation_run_data.project_id,
|
||||||
model_name,
|
model_name,
|
||||||
|
@ -139,8 +151,6 @@ class AutomationContext:
|
||||||
if isinstance(branch_create, Exception):
|
if isinstance(branch_create, Exception):
|
||||||
raise branch_create
|
raise branch_create
|
||||||
model_id = branch_create
|
model_id = branch_create
|
||||||
else:
|
|
||||||
model_id = branch.id
|
|
||||||
|
|
||||||
root_object_id = operations.send(
|
root_object_id = operations.send(
|
||||||
root_object,
|
root_object,
|
||||||
|
@ -174,7 +184,8 @@ class AutomationContext:
|
||||||
) -> None:
|
) -> None:
|
||||||
link_resources = (
|
link_resources = (
|
||||||
[
|
[
|
||||||
f"{self.automation_run_data.model_id}@{self.automation_run_data.version_id}"
|
f"{t.payload.model_id}@{t.payload.version_id}"
|
||||||
|
for t in self.automation_run_data.triggers
|
||||||
]
|
]
|
||||||
if include_source_model_version
|
if include_source_model_version
|
||||||
else []
|
else []
|
||||||
|
@ -194,47 +205,26 @@ class AutomationContext:
|
||||||
"""Report the current run status to the project of this automation."""
|
"""Report the current run status to the project of this automation."""
|
||||||
query = gql(
|
query = gql(
|
||||||
"""
|
"""
|
||||||
mutation ReportFunctionRunStatus(
|
mutation AutomateFunctionRunStatusReport(
|
||||||
$automationId: String!,
|
$functionRunId: String!
|
||||||
$automationRevisionId: String!,
|
$status: AutomateRunStatus!
|
||||||
$automationRunId: String!,
|
|
||||||
$versionId: String!,
|
|
||||||
$functionId: String!,
|
|
||||||
$functionName: String!,
|
|
||||||
$functionLogo: String,
|
|
||||||
$runStatus: AutomationRunStatus!
|
|
||||||
$elapsed: Float!
|
|
||||||
$contextView: String
|
|
||||||
$resultVersionIds: [String!]!
|
|
||||||
$statusMessage: String
|
$statusMessage: String
|
||||||
$objectResults: JSONObject
|
$results: JSONObject
|
||||||
|
$contextView: String
|
||||||
){
|
){
|
||||||
automationMutations {
|
automateFunctionRunStatusReport(input: {
|
||||||
functionRunStatusReport(input: {
|
functionRunId: $functionRunId
|
||||||
automationId: $automationId
|
status: $status
|
||||||
automationRevisionId: $automationRevisionId
|
statusMessage: $statusMessage
|
||||||
automationRunId: $automationRunId
|
contextView: $contextView
|
||||||
versionId: $versionId
|
results: $results
|
||||||
functionRuns: [
|
})
|
||||||
{
|
|
||||||
functionId: $functionId
|
|
||||||
functionName: $functionName
|
|
||||||
functionLogo: $functionLogo
|
|
||||||
status: $runStatus,
|
|
||||||
contextView: $contextView,
|
|
||||||
elapsed: $elapsed,
|
|
||||||
resultVersionIds: $resultVersionIds,
|
|
||||||
statusMessage: $statusMessage
|
|
||||||
results: $objectResults
|
|
||||||
}]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
if self.run_status in [AutomationStatus.SUCCEEDED, AutomationStatus.FAILED]:
|
if self.run_status in [AutomationStatus.SUCCEEDED, AutomationStatus.FAILED]:
|
||||||
object_results = {
|
object_results = {
|
||||||
"version": "1.0.0",
|
"version": 1,
|
||||||
"values": {
|
"values": {
|
||||||
"objectResults": self._automation_result.model_dump(by_alias=True)[
|
"objectResults": self._automation_result.model_dump(by_alias=True)[
|
||||||
"objectResults"
|
"objectResults"
|
||||||
|
@ -246,19 +236,11 @@ class AutomationContext:
|
||||||
object_results = None
|
object_results = None
|
||||||
|
|
||||||
params = {
|
params = {
|
||||||
"automationId": self.automation_run_data.automation_id,
|
"functionRunId": self.automation_run_data.function_run_id,
|
||||||
"automationRevisionId": self.automation_run_data.automation_revision_id,
|
"status": self.run_status.value,
|
||||||
"automationRunId": self.automation_run_data.automation_run_id,
|
|
||||||
"versionId": self.automation_run_data.version_id,
|
|
||||||
"functionId": self.automation_run_data.function_id,
|
|
||||||
"functionName": self.automation_run_data.function_name,
|
|
||||||
"functionLogo": self.automation_run_data.function_logo,
|
|
||||||
"runStatus": self.run_status.value,
|
|
||||||
"statusMessage": self._automation_result.status_message,
|
"statusMessage": self._automation_result.status_message,
|
||||||
|
"results": object_results,
|
||||||
"contextView": self._automation_result.result_view,
|
"contextView": self._automation_result.result_view,
|
||||||
"elapsed": self.elapsed(),
|
|
||||||
"resultVersionIds": self._automation_result.result_versions,
|
|
||||||
"objectResults": object_results,
|
|
||||||
}
|
}
|
||||||
print(f"Reporting run status with content: {params}")
|
print(f"Reporting run status with content: {params}")
|
||||||
self.speckle_client.httpclient.execute(query, params)
|
self.speckle_client.httpclient.execute(query, params)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
""""""
|
""""""
|
||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List, Literal, Optional
|
||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict, Field
|
from pydantic import BaseModel, ConfigDict, Field
|
||||||
from stringcase import camelcase
|
from stringcase import camelcase
|
||||||
|
@ -12,22 +13,30 @@ class AutomateBase(BaseModel):
|
||||||
model_config = ConfigDict(alias_generator=camelcase, populate_by_name=True)
|
model_config = ConfigDict(alias_generator=camelcase, populate_by_name=True)
|
||||||
|
|
||||||
|
|
||||||
|
class VersionCreationTriggerPayload(AutomateBase):
|
||||||
|
"""Represents the version creation trigger payload."""
|
||||||
|
|
||||||
|
model_id: str
|
||||||
|
version_id: str
|
||||||
|
|
||||||
|
|
||||||
|
class VersionCreationTrigger(AutomateBase):
|
||||||
|
"""Represents a single version creation trigger for the automation run."""
|
||||||
|
|
||||||
|
trigger_type: Literal["versionCreation"]
|
||||||
|
payload: VersionCreationTriggerPayload
|
||||||
|
|
||||||
|
|
||||||
class AutomationRunData(BaseModel):
|
class AutomationRunData(BaseModel):
|
||||||
"""Values of the project / model that triggered the run of this function."""
|
"""Values of the project / model that triggered the run of this function."""
|
||||||
|
|
||||||
project_id: str
|
project_id: str
|
||||||
model_id: str
|
|
||||||
branch_name: str
|
|
||||||
version_id: str
|
|
||||||
speckle_server_url: str
|
speckle_server_url: str
|
||||||
|
|
||||||
automation_id: str
|
automation_id: str
|
||||||
automation_revision_id: str
|
|
||||||
automation_run_id: str
|
automation_run_id: str
|
||||||
|
function_run_id: str
|
||||||
|
|
||||||
function_id: str
|
triggers: List[VersionCreationTrigger]
|
||||||
function_name: str
|
|
||||||
function_logo: Optional[str]
|
|
||||||
|
|
||||||
model_config = ConfigDict(
|
model_config = ConfigDict(
|
||||||
alias_generator=camelcase, populate_by_name=True, protected_namespaces=()
|
alias_generator=camelcase, populate_by_name=True, protected_namespaces=()
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
from typing import Optional
|
from typing import Optional, Union
|
||||||
|
|
||||||
from specklepy.api.models import Branch
|
from specklepy.api.models import Branch
|
||||||
from specklepy.core.api.resources.branch import Resource as CoreResource
|
from specklepy.core.api.resources.branch import Resource as CoreResource
|
||||||
from specklepy.logging import metrics
|
from specklepy.logging import metrics
|
||||||
|
from specklepy.logging.exceptions import SpeckleException
|
||||||
|
|
||||||
|
|
||||||
class Resource(CoreResource):
|
class Resource(CoreResource):
|
||||||
|
@ -31,7 +32,9 @@ class Resource(CoreResource):
|
||||||
metrics.track(metrics.SDK, self.account, {"name": "Branch Create"})
|
metrics.track(metrics.SDK, self.account, {"name": "Branch Create"})
|
||||||
return super().create(stream_id, name, description)
|
return super().create(stream_id, name, description)
|
||||||
|
|
||||||
def get(self, stream_id: str, name: str, commits_limit: int = 10):
|
def get(
|
||||||
|
self, stream_id: str, name: str, commits_limit: int = 10
|
||||||
|
) -> Union[Branch, None, SpeckleException]:
|
||||||
"""Get a branch by name from a stream
|
"""Get a branch by name from a stream
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
Загрузка…
Ссылка в новой задаче