mirror of
https://github.com/langgenius/dify.git
synced 2026-09-19 10:11:30 +08:00
feat: app deployment v2 (#39829)
Co-authored-by: zhangx1n <zhangxin@dify.ai> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
zhangx1n
autofix-ci[bot]
parent
ef8544b173
commit
7aba539e82
@@ -315,6 +315,9 @@ class WorkflowResponse(ResponseModel):
|
||||
)
|
||||
hash: str = Field(validation_alias=AliasChoices("unique_hash", "hash"))
|
||||
version: str
|
||||
# NULL for drafts and for versions published before numbering was introduced; those
|
||||
# render as "Untitled Version" instead of `#N`. Never 0, so clients must test for null.
|
||||
version_number: int | None = None
|
||||
marked_name: str
|
||||
marked_comment: str
|
||||
created_by: SimpleAccount | None = Field(
|
||||
|
||||
@@ -5,13 +5,15 @@ to attribute the created app; workspace/membership validation is done by the
|
||||
Go admin-api caller.
|
||||
"""
|
||||
|
||||
from uuid import UUID
|
||||
|
||||
from flask import request
|
||||
from flask_restx import Resource
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import BaseModel, Field, ValidationError, field_validator
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from controllers.common.schema import register_schema_model
|
||||
from controllers.common.schema import query_params_from_model, register_schema_model
|
||||
from controllers.console.wraps import setup_required
|
||||
from controllers.inner_api import inner_api_ns
|
||||
from controllers.inner_api.wraps import enterprise_inner_api_only
|
||||
@@ -20,6 +22,7 @@ from models import Account, App
|
||||
from models.account import AccountStatus
|
||||
from services.app_dsl_service import AppDslService
|
||||
from services.entities.dsl_entities import ImportMode, ImportStatus
|
||||
from services.errors.app import IsDraftWorkflowError, WorkflowNotFoundError
|
||||
|
||||
|
||||
class InnerAppDSLImportPayload(BaseModel):
|
||||
@@ -29,6 +32,18 @@ class InnerAppDSLImportPayload(BaseModel):
|
||||
description: str | None = Field(default=None, description="Override app description from DSL")
|
||||
|
||||
|
||||
class EnterpriseAppDSLExportQuery(BaseModel):
|
||||
include_secret: bool = Field(default=False, description="Whether to include secret values in the exported DSL")
|
||||
workflow_id: UUID | None = Field(default=None, description="Published workflow version ID to export")
|
||||
|
||||
@field_validator("include_secret", mode="before")
|
||||
@classmethod
|
||||
def parse_include_secret(cls, value: object) -> bool:
|
||||
if isinstance(value, str):
|
||||
return value.lower() == "true"
|
||||
return bool(value)
|
||||
|
||||
|
||||
register_schema_model(inner_api_ns, InnerAppDSLImportPayload)
|
||||
|
||||
|
||||
@@ -82,24 +97,48 @@ class EnterpriseAppDSLExport(Resource):
|
||||
@enterprise_inner_api_only
|
||||
@inner_api_ns.doc(
|
||||
"enterprise_app_dsl_export",
|
||||
params=query_params_from_model(EnterpriseAppDSLExportQuery),
|
||||
responses={
|
||||
200: "Export successful",
|
||||
404: "App not found",
|
||||
400: "Invalid workflow ID or unpublished workflow version",
|
||||
404: "App or workflow version not found",
|
||||
},
|
||||
)
|
||||
def get(self, app_id: str):
|
||||
"""Export an app's DSL as YAML."""
|
||||
include_secret = request.args.get("include_secret", "false").lower() == "true"
|
||||
try:
|
||||
query = EnterpriseAppDSLExportQuery.model_validate(request.args.to_dict(flat=True))
|
||||
except ValidationError:
|
||||
return {
|
||||
"code": "invalid_workflow_id",
|
||||
"message": "workflow_id must be a valid UUID",
|
||||
"status": 400,
|
||||
}, 400
|
||||
|
||||
workflow_id = str(query.workflow_id) if query.workflow_id else None
|
||||
|
||||
app_model = db.session.get(App, app_id)
|
||||
if not app_model:
|
||||
return {"message": "app not found"}, 404
|
||||
|
||||
data = AppDslService.export_dsl(
|
||||
app_model=app_model,
|
||||
session=db.session(),
|
||||
include_secret=include_secret,
|
||||
)
|
||||
if not workflow_id:
|
||||
data = AppDslService.export_dsl(
|
||||
app_model=app_model,
|
||||
session=db.session(),
|
||||
include_secret=query.include_secret,
|
||||
)
|
||||
else:
|
||||
try:
|
||||
data = AppDslService.export_dsl(
|
||||
app_model=app_model,
|
||||
session=db.session(),
|
||||
include_secret=query.include_secret,
|
||||
workflow_id=workflow_id,
|
||||
)
|
||||
except WorkflowNotFoundError as exc:
|
||||
return {"code": "workflow_version_not_found", "message": str(exc), "status": 404}, 404
|
||||
except IsDraftWorkflowError as exc:
|
||||
return {"code": "workflow_version_not_published", "message": str(exc), "status": 400}, 400
|
||||
|
||||
return {"data": data}, 200
|
||||
|
||||
|
||||
Reference in New Issue
Block a user