projects -> scripts (#3123)

This commit is contained in:
Shuchang Zheng
2025-08-06 22:23:38 -07:00
committed by GitHub
parent 75eadef0e1
commit 1a4bf1df1a
17 changed files with 660 additions and 538 deletions

View File

@@ -7,19 +7,19 @@ from datetime import datetime
import structlog
from fastapi import BackgroundTasks
from skyvern.exceptions import ProjectNotFound
from skyvern.exceptions import ScriptNotFound
from skyvern.forge import app
from skyvern.schemas.projects import FileNode, ProjectFileCreate
from skyvern.schemas.scripts import FileNode, ScriptFileCreate
LOG = structlog.get_logger(__name__)
async def build_file_tree(
files: list[ProjectFileCreate],
files: list[ScriptFileCreate],
organization_id: str,
project_id: str,
project_version: int,
project_revision_id: str,
script_id: str,
script_version: int,
script_revision_id: str,
) -> dict[str, FileNode]:
"""Build a hierarchical file tree from a list of files and upload the files to s3 with the same tree structure."""
file_tree: dict[str, FileNode] = {}
@@ -32,24 +32,24 @@ async def build_file_tree(
# Create artifact and upload to S3
try:
artifact_id = await app.ARTIFACT_MANAGER.create_project_file_artifact(
artifact_id = await app.ARTIFACT_MANAGER.create_script_file_artifact(
organization_id=organization_id,
project_id=project_id,
project_version=project_version,
script_id=script_id,
script_version=script_version,
file_path=file.path,
data=content_bytes,
)
LOG.debug(
"Created project file artifact",
"Created script file artifact",
artifact_id=artifact_id,
file_path=file.path,
project_id=project_id,
project_version=project_version,
script_id=script_id,
script_version=script_version,
)
# create a project file record
await app.DATABASE.create_project_file(
project_revision_id=project_revision_id,
project_id=project_id,
# create a script file record
await app.DATABASE.create_script_file(
script_revision_id=script_revision_id,
script_id=script_id,
organization_id=organization_id,
file_path=file.path,
file_name=file.path.split("/")[-1],
@@ -61,11 +61,11 @@ async def build_file_tree(
)
except Exception:
LOG.exception(
"Failed to create project file artifact",
"Failed to create script file artifact",
file_path=file.path,
project_id=project_id,
project_version=project_version,
project_revision_id=project_revision_id,
script_id=script_id,
script_version=script_version,
script_revision_id=script_revision_id,
)
raise
@@ -96,43 +96,43 @@ async def build_file_tree(
return file_tree
async def execute_project(
project_id: str,
async def execute_script(
script_id: str,
organization_id: str,
background_tasks: BackgroundTasks | None = None,
) -> None:
# TODO: assume the project only has one ProjectFile called main.py
# step 1: get the project revision
# step 2: get the project files
# step 3: copy the project files to the local directory
# step 4: execute the project
# TODO: assume the script only has one ScriptFile called main.py
# step 1: get the script revision
# step 2: get the script files
# step 3: copy the script files to the local directory
# step 4: execute the script
# step 1: get the project revision
project = await app.DATABASE.get_project(
project_id=project_id,
# step 1: get the script revision
script = await app.DATABASE.get_script(
script_id=script_id,
organization_id=organization_id,
)
if not project:
raise ProjectNotFound(project_id=project_id)
if not script:
raise ScriptNotFound(script_id=script_id)
# step 2: get the project files
project_files = await app.DATABASE.get_project_files(
project_revision_id=project.project_revision_id, organization_id=organization_id
# step 2: get the script files
script_files = await app.DATABASE.get_script_files(
script_revision_id=script.script_revision_id, organization_id=organization_id
)
# step 3: copy the project files to the local directory
for file in project_files:
# step 3: copy the script files to the local directory
for file in script_files:
# retrieve the artifact
if not file.artifact_id:
continue
artifact = await app.DATABASE.get_artifact_by_id(file.artifact_id, organization_id)
if not artifact:
LOG.error("Artifact not found", artifact_id=file.artifact_id, project_id=project_id)
LOG.error("Artifact not found", artifact_id=file.artifact_id, script_id=script_id)
continue
file_content = await app.ARTIFACT_MANAGER.retrieve_artifact(artifact)
if not file_content:
continue
file_path = os.path.join(project.project_id, file.file_path)
file_path = os.path.join(script.script_id, file.file_path)
# create the directory if it doesn't exist
os.makedirs(os.path.dirname(file_path), exist_ok=True)
@@ -154,7 +154,7 @@ async def execute_project(
with open(file_path, "wb") as f:
f.write(file_content)
# step 4: execute the project
# step 4: execute the script
if background_tasks:
background_tasks.add_task(subprocess.run, ["python", f"{project.project_id}/main.py"])
LOG.info("Project executed successfully", project_id=project_id)
background_tasks.add_task(subprocess.run, ["python", f"{script.script_id}/main.py"])
LOG.info("Script executed successfully", script_id=script_id)