Skip to content

Commit ba3ec2c

Browse files
authored
feat(workflow): harden dependency-aware YAML imports (#1623)
* feat(workflow): harden dependency-aware YAML imports Signed-off-by: yjlu12 <1064690083@qq.com> * fix(workflow): complete safe cross-environment imports Signed-off-by: yjlu12 <1064690083@qq.com> * refactor(workflow): satisfy import CI quality gates Signed-off-by: yjlu12 <1064690083@qq.com> * style(workflow): align import helper formatting Signed-off-by: yjlu12 <1064690083@qq.com> * refactor(workflow): extract YAML import parser Signed-off-by: yjlu12 <1064690083@qq.com> --------- Signed-off-by: yjlu12 <1064690083@qq.com>
1 parent 327eee2 commit ba3ec2c

69 files changed

Lines changed: 12316 additions & 451 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

console/backend/commons/src/main/java/com/iflytek/astron/console/commons/constant/ResponseEnum.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ public enum ResponseEnum {
283283
WORKFLOW_MCP_SERVER_REGISTRY_FAILED(8126, "work.flow.mcp.server.registry.failed"),
284284
WORKFLOW_SKILL_API_NOT_READY(8127, "workflow.skill.api.not.ready"),
285285
WORKFLOW_SKILL_NAME_DESC_EMPTY(8128, "workflow.skill.name.desc.empty"),
286+
WORKFLOW_IMPORT_DEPENDENCY_UNRESOLVED(8129, "workflow.import.dependency.unresolved"),
286287

287288

288289
// Plugins 8300 - 8500

console/backend/commons/src/main/resources/messages_en.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ work.flow.dls.upload.failed=Your uploaded DSL file is incorrect, please retry
268268
work.flow.mcp.server.registry.failed=Mcp-server registration failed
269269
workflow.skill.api.not.ready=Please publish this workflow as an API and bind an app before exporting it as a Skill
270270
workflow.skill.name.desc.empty=Please complete the workflow name and description before exporting it as a Skill
271+
workflow.import.dependency.unresolved=Resolve imported workflow dependencies before debugging, building, or publishing
271272
failed.get.trace=Trace log retrieval failed
272273

273274
# Plugin 8300+

console/backend/commons/src/main/resources/messages_zh.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ work.flow.dls.upload.failed=您上传的DSL文件有误,请重试
280280
work.flow.mcp.server.registry.failed=Mcp-server 注册失败
281281
workflow.skill.api.not.ready=请先将该工作流发布为API并绑定应用成功后,再导出为Skill
282282
workflow.skill.name.desc.empty=请先补充工作流名称和描述后,再导出为Skill
283+
workflow.import.dependency.unresolved=请先解决导入工作流中未匹配的依赖,再进行调试、构建或发布
283284
failed.get.trace=Trace日志获取失败
284285

285286
# 插件 8300+

console/backend/hub/src/main/java/com/iflytek/astron/console/hub/service/publish/ReleaseManageClientService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@
88
public interface ReleaseManageClientService {
99
String getVersionNameByBotId(Long botId, Long spaceId, HttpServletRequest request);
1010

11-
void releaseBotApi(Integer botId, String flowId, String versionName, Long spaceId, HttpServletRequest request);
11+
void releaseBotApi(Integer botId, String flowId, String versionName, String executionUid,
12+
Long spaceId, HttpServletRequest request);
1213
}

console/backend/hub/src/main/java/com/iflytek/astron/console/hub/service/publish/impl/McpServiceImpl.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ private String getVersionName(Integer botId, String currentUid, Long spaceId) {
144144
return generateDefaultVersion();
145145
}
146146

147+
} catch (BusinessException e) {
148+
throw e;
147149
} catch (Exception e) {
148150
log.error("Exception occurred while getting version name for MCP: botId={}", botId, e);
149151
return generateDefaultVersion();

console/backend/hub/src/main/java/com/iflytek/astron/console/hub/service/publish/impl/PublishApiServiceImpl.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ public BotApiInfoDTO createBotApi(CreateBotApiVo createBotApiVo, HttpServletRequ
149149
} else {
150150
throw new BusinessException(ResponseEnum.BOT_TYPE_NOT_SUPPORT);
151151
}
152+
} catch (BusinessException e) {
153+
throw e;
152154
} catch (Exception e) {
153155
log.error("PublishApiServiceImpl.createBotApi : create Bot api error, request: {}", createBotApiVo, e);
154156
throw new BusinessException(ResponseEnum.BOT_API_CREATE_ERROR);
@@ -203,7 +205,7 @@ private BotApiInfoDTO createMaasApi(
203205
String flowId = userLangChainInfo.getFlowId();
204206
// Synchronize with Maas service
205207
String versionName = releaseManageClientService.getVersionNameByBotId(Long.valueOf(botId), spaceId, request);
206-
releaseManageClientService.releaseBotApi(botId, flowId, versionName, spaceId, request);
208+
releaseManageClientService.releaseBotApi(botId, flowId, versionName, uid, spaceId, request);
207209
maasUtil.createApi(flowId, appMst.getAppId(), versionName);
208210

209211
ChatBotApi chatBotApi = ChatBotApi.builder()

console/backend/hub/src/main/java/com/iflytek/astron/console/hub/service/publish/impl/ReleaseManageClientServiceImpl.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ public String getVersionNameByBotId(Long botId, Long spaceId, HttpServletRequest
5151
}
5252

5353
@Override
54-
public void releaseBotApi(Integer botId, String flowId, String versionName, Long spaceId, HttpServletRequest request) {
54+
public void releaseBotApi(Integer botId, String flowId, String versionName, String executionUid,
55+
Long spaceId, HttpServletRequest request) {
5556
if (botId == null || StrUtil.isBlank(flowId) || StrUtil.isBlank(versionName)) {
5657
throw new BusinessException(ResponseEnum.WORKFLOW_VERSION_PUBLISH_FAILED);
5758
}
@@ -70,7 +71,8 @@ public void releaseBotApi(Integer botId, String flowId, String versionName, Long
7071
workflowVersion.setDescription("");
7172
workflowVersion.setName(versionName);
7273

73-
ApiResult<JSONObject> response = versionService.createForBoundBotPublish(workflowVersion);
74+
ApiResult<JSONObject> response = versionService.createForBoundBotPublish(
75+
workflowVersion, executionUid, spaceId);
7476
if (response == null || response.code() != 0 || response.data() == null) {
7577
log.error("releaseBotApi - Failed to create workflow version, botId={}, flowId={}, versionName={}, spaceId={}",
7678
botId, flowId, versionName, spaceId);

console/backend/hub/src/main/java/com/iflytek/astron/console/hub/service/workflow/impl/WorkflowReleaseServiceImpl.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.iflytek.astron.console.commons.service.data.UserLangChainDataService;
55
import com.iflytek.astron.console.commons.mapper.bot.ChatBotApiMapper;
66
import com.iflytek.astron.console.commons.dto.bot.ChatBotApi;
7+
import com.iflytek.astron.console.commons.exception.BusinessException;
78
import com.iflytek.astron.console.commons.util.MaasUtil;
89
import com.iflytek.astron.console.toolkit.common.constant.WorkflowConst;
910
import com.iflytek.astron.console.toolkit.entity.table.workflow.WorkflowVersion;
@@ -82,7 +83,7 @@ public WorkflowReleaseResponseDto publishWorkflow(Integer botId, String uid, Lon
8283
request.setDescription("");
8384
request.setName(versionName);
8485

85-
WorkflowReleaseResponseDto response = createWorkflowVersion(request);
86+
WorkflowReleaseResponseDto response = createWorkflowVersion(request, uid, spaceId);
8687
if (!response.getSuccess()) {
8788
return response;
8889
}
@@ -104,6 +105,8 @@ public WorkflowReleaseResponseDto publishWorkflow(Integer botId, String uid, Lon
104105

105106
return response;
106107

108+
} catch (BusinessException e) {
109+
throw e;
107110
} catch (Exception e) {
108111
log.error("Workflow bot publish failed: botId={}, uid={}, spaceId={}", botId, uid, spaceId, e);
109112
return createErrorResponse("Publish failed: " + e.getMessage());
@@ -166,7 +169,8 @@ private boolean isVersionExists(Integer botId, String versionName) {
166169
}
167170
}
168171

169-
private WorkflowReleaseResponseDto createWorkflowVersion(WorkflowReleaseRequestDto request) {
172+
private WorkflowReleaseResponseDto createWorkflowVersion(
173+
WorkflowReleaseRequestDto request, String executionUid, Long executionSpaceId) {
170174
log.info("Creating workflow version: request={}", request);
171175

172176
try {
@@ -178,7 +182,8 @@ private WorkflowReleaseResponseDto createWorkflowVersion(WorkflowReleaseRequestD
178182
workflowVersion.setDescription(request.getDescription());
179183
workflowVersion.setName(request.getName());
180184

181-
var response = versionService.createForBoundBotPublish(workflowVersion);
185+
var response = versionService.createForBoundBotPublish(
186+
workflowVersion, executionUid, executionSpaceId);
182187
JSONObject data = response == null ? null : response.data();
183188
if (response == null || response.code() != 0 || data == null) {
184189
return createErrorResponse("Invalid response data format");
@@ -196,6 +201,8 @@ private WorkflowReleaseResponseDto createWorkflowVersion(WorkflowReleaseRequestD
196201
result.getWorkflowVersionId(), result.getWorkflowVersionName());
197202
return result;
198203

204+
} catch (BusinessException e) {
205+
throw e;
199206
} catch (Exception e) {
200207
log.error("Exception occurred while creating workflow version: request={}", request, e);
201208
return createErrorResponse("Exception occurred while creating version: " + e.getMessage());
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
INSERT IGNORE INTO `agent_space_permission`
2+
(`module`, `point`, `description`, `permission_key`, `owner`, `admin`, `member`, `available_expired`, `create_time`, `update_time`)
3+
VALUES
4+
('Workflow', 'Import Workflow', 'Import Workflow', 'WorkflowController_importWorkflow_POST', 1, 1, 1, 0, NOW(), NOW());

console/backend/hub/src/test/java/com/iflytek/astron/console/hub/listener/WorkflowBotPublishListenerTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.mockito.junit.jupiter.MockitoExtension;
1717

1818
import static org.assertj.core.api.Assertions.assertThatThrownBy;
19+
import static org.mockito.Mockito.verify;
1920
import static org.mockito.Mockito.when;
2021

2122
@ExtendWith(MockitoExtension.class)
@@ -89,4 +90,27 @@ void handleBotPublishStatusChangedShouldFailWhenWorkflowBotHasNoFlowId() {
8990
.extracting("responseEnum")
9091
.isEqualTo(ResponseEnum.WORKFLOW_VERSION_PUBLISH_FAILED);
9192
}
93+
94+
@Test
95+
void handleBotPublishStatusChangedShouldPreserveUnresolvedDependencyError() {
96+
ChatBotBase botBase = new ChatBotBase();
97+
botBase.setId(25);
98+
botBase.setVersion(BotTypeEnum.WORKFLOW_BOT.getType());
99+
when(chatBotBaseMapper.selectById(25)).thenReturn(botBase);
100+
when(userLangChainDataService.findFlowIdByBotId(25)).thenReturn("flow-1");
101+
BusinessException unresolved =
102+
new BusinessException(ResponseEnum.WORKFLOW_IMPORT_DEPENDENCY_UNRESOLVED);
103+
when(workflowReleaseService.publishWorkflow(25, "requester-uid", 1L, "MARKET"))
104+
.thenThrow(unresolved);
105+
106+
BotPublishStatusChangedEvent event = new BotPublishStatusChangedEvent(
107+
this, 25, "requester-uid", 1L, "PUBLISH", null, 1, "MARKET");
108+
109+
assertThatThrownBy(() -> listener.handleBotPublishStatusChanged(event))
110+
.isSameAs(unresolved)
111+
.extracting("code")
112+
.isEqualTo(ResponseEnum.WORKFLOW_IMPORT_DEPENDENCY_UNRESOLVED.getCode());
113+
114+
verify(workflowReleaseService).publishWorkflow(25, "requester-uid", 1L, "MARKET");
115+
}
92116
}

0 commit comments

Comments
 (0)