fix: ToolSourceUpdater bug and add docker volume mount

This commit is contained in:
jade
2026-07-10 10:30:59 +09:00
parent 67b83ff356
commit b199dad455
13 changed files with 178 additions and 14 deletions

View File

@@ -44,7 +44,10 @@ public class PodScaffolder {
}
public static String scaffoldPod(String moduleName, String portStr, String shortName, String author, String createDate) throws IOException {
Path modulePath = Paths.get(moduleName);
String envSourceDir = System.getenv("AXHUB_SOURCE_DIR");
Path rootDir = envSourceDir != null ? Paths.get(envSourceDir) : Paths.get(".");
Path modulePath = rootDir.resolve(Paths.get(moduleName));
if (Files.exists(modulePath)) {
return "[오류] 이미 존재하는 모듈입니다: " + moduleName;
}
@@ -202,7 +205,7 @@ public class PodScaffolder {
Files.writeString(resPath.resolve("logback-spring.xml"), logbackXml);
log.append("[5/6] settings.gradle 에 모듈 등록 중...\n");
Path settingsPath = Paths.get("settings.gradle");
Path settingsPath = rootDir.resolve(Paths.get("settings.gradle"));
if (Files.exists(settingsPath)) {
String settings = Files.readString(settingsPath);
if (!settings.contains("include '" + moduleName + "'")) {
@@ -211,7 +214,7 @@ public class PodScaffolder {
}
log.append("[6/6] docker-compose.yml 에 서비스 추가 중...\n");
Path dockerComposePath = Paths.get("docker-compose.yml");
Path dockerComposePath = rootDir.resolve(Paths.get("docker-compose.yml"));
if (Files.exists(dockerComposePath)) {
String compose = Files.readString(dockerComposePath);
String serviceName = moduleName.replace("axhub-", ""); // e.g. tool-payment

View File

@@ -81,8 +81,11 @@ public class ToolScaffolder {
}
public static String scaffold(String baseName, String interfaceId, String description, String group, String routingType, String moduleName, String author, String createDate, boolean register) throws IOException {
Path serviceDir = Paths.get(moduleName, BASE_PACKAGE_PATH, "service");
Path dtoDir = Paths.get(moduleName, BASE_PACKAGE_PATH, "dto");
String envSourceDir = System.getenv("AXHUB_SOURCE_DIR");
Path rootDir = envSourceDir != null ? Paths.get(envSourceDir) : Paths.get(".");
Path serviceDir = rootDir.resolve(Paths.get(moduleName, BASE_PACKAGE_PATH, "service"));
Path dtoDir = rootDir.resolve(Paths.get(moduleName, BASE_PACKAGE_PATH, "dto"));
Files.createDirectories(serviceDir);
Files.createDirectories(dtoDir);
@@ -204,7 +207,7 @@ public class ToolScaffolder {
Files.writeString(serviceDir.resolve(baseName + "Service.java"), serviceContent);
// Append to YAML
Path resourcesDir = Paths.get(moduleName, "src/main/resources");
Path resourcesDir = rootDir.resolve(Paths.get(moduleName, "src/main/resources"));
Files.createDirectories(resourcesDir);
Path yamlPath = resourcesDir.resolve("application-local.yml");

View File

@@ -14,7 +14,8 @@ public class ToolSourceUpdater {
public static void updateToolSource(String toolName, String domainGroup, String description, boolean register) throws Exception {
// 1. Find all *Service.java files in axhub-tool-* directories
Path rootDir = Paths.get(".");
String envSourceDir = System.getenv("AXHUB_SOURCE_DIR");
Path rootDir = envSourceDir != null ? Paths.get(envSourceDir) : Paths.get(".");
List<Path> javaFiles;
try (Stream<Path> paths = Files.walk(rootDir)) {
@@ -29,7 +30,13 @@ public class ToolSourceUpdater {
String content = null;
// 2. Find the specific file for the tool
Pattern namePattern = Pattern.compile("@McpFunction\\\\s*\\\\([^)]*name\\\\s*=\\\\s*\\\"" + Pattern.quote(toolName) + "\\\"", Pattern.DOTALL);
String functionName = toolName;
if (toolName.contains("_")) {
functionName = toolName.substring(toolName.indexOf("_") + 1);
}
Pattern namePattern = Pattern.compile("@McpFunction\\s*\\([^)]*name\\s*=\\s*\"" + Pattern.quote(toolName) + "\"", Pattern.DOTALL);
Pattern namePattern2 = Pattern.compile("@McpFunction\\s*\\([^)]*name\\s*=\\s*\"" + Pattern.quote(functionName) + "\"", Pattern.DOTALL);
for (Path path : javaFiles) {
String text = Files.readString(path);
@@ -37,6 +44,11 @@ public class ToolSourceUpdater {
targetFile = path;
content = text;
break;
} else if (namePattern2.matcher(text).find()) {
targetFile = path;
content = text;
toolName = functionName; // Use baseName for subsequent replacements
break;
}
}
@@ -46,7 +58,7 @@ public class ToolSourceUpdater {
// 3. Update @McpTool group
if (domainGroup != null && !domainGroup.trim().isEmpty()) {
Pattern groupPattern = Pattern.compile("(@McpTool\\\\s*\\\\([^)]*group\\\\s*=\\\\s*\\\")([^\\\"]+)(\\\")", Pattern.DOTALL);
Pattern groupPattern = Pattern.compile("(@McpTool\\s*\\([^)]*group\\s*=\\s*\")([^\"]+)(\")", Pattern.DOTALL);
Matcher groupMatcher = groupPattern.matcher(content);
if (groupMatcher.find()) {
content = groupMatcher.replaceFirst("$1" + domainGroup + "$3");
@@ -55,7 +67,7 @@ public class ToolSourceUpdater {
// 4. Update @McpFunction description
if (description != null) {
Pattern funcPattern = Pattern.compile("(@McpFunction\\\\s*\\\\([^)]*name\\\\s*=\\\\s*\\\"" + Pattern.quote(toolName) + "\\\"[^)]*description\\\\s*=\\\\s*\\\")([^\\\"]+)(\\\")", Pattern.DOTALL);
Pattern funcPattern = Pattern.compile("(@McpFunction\\s*\\([^)]*name\\s*=\\s*\"" + Pattern.quote(toolName) + "\"[^)]*description\\s*=\\s*\")([^\"]+)(\")", Pattern.DOTALL);
Matcher funcMatcher = funcPattern.matcher(content);
if (funcMatcher.find()) {
content = funcMatcher.replaceFirst("$1" + description.replace("\\", "\\\\").replace("$", "\\\\$") + "$3");
@@ -63,12 +75,12 @@ public class ToolSourceUpdater {
}
// 5. Update register flag
Pattern regPattern = Pattern.compile("(@McpFunction\\\\s*\\\\([^)]*name\\\\s*=\\\\s*\\\"" + Pattern.quote(toolName) + "\\\"[^)]*register\\\\s*=\\\\s*)(true|false)([^a-zA-Z0-9])", Pattern.DOTALL);
Pattern regPattern = Pattern.compile("(@McpFunction\\s*\\([^)]*name\\s*=\\s*\"" + Pattern.quote(toolName) + "\"[^)]*register\\s*=\\s*)(true|false)([^a-zA-Z0-9])", Pattern.DOTALL);
Matcher regMatcher = regPattern.matcher(content);
if (regMatcher.find()) {
content = regMatcher.replaceFirst("$1" + register + "$3");
} else {
Pattern addRegPattern = Pattern.compile("(@McpFunction\\\\s*\\\\([^)]*name\\\\s*=\\\\s*\\\"" + Pattern.quote(toolName) + "\\\")", Pattern.DOTALL);
Pattern addRegPattern = Pattern.compile("(@McpFunction\\s*\\([^)]*name\\s*=\\s*\"" + Pattern.quote(toolName) + "\")", Pattern.DOTALL);
Matcher addRegMatcher = addRegPattern.matcher(content);
if (addRegMatcher.find()) {
content = addRegMatcher.replaceFirst("$1, register = " + register);

View File

@@ -0,0 +1,50 @@
package io.shinhanlife.glow.util;
import io.shinhanlife.glow.GlowMciFieldInfo;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
public class GlowMciParserTest {
public static class DummyMciDto {
@GlowMciFieldInfo(order = 1, length = 10)
private String customerId;
@GlowMciFieldInfo(order = 2, length = 15)
private String name;
@GlowMciFieldInfo(order = 3, length = 3)
private int age;
public String getCustomerId() { return customerId; }
public String getName() { return name; }
public int getAge() { return age; }
}
@Test
@DisplayName("고정 길이 MCI 문자열을 DTO로 파싱하는 테스트")
public void testParseFixedLengthString() {
// given: 고정 길이 텍스트 (총 28자리)
// ID(10) + Name(15) + Age(3)
String rawMciString = "CUST000001KIM SHINHAN 035";
// when
DummyMciDto result = GlowMciParser.parse(rawMciString, DummyMciDto.class);
// then
System.out.println("==================================================");
System.out.println("✅ [원본 MCI 전문] : [" + rawMciString + "]");
System.out.println("✅ [파싱된 ID (10자리)] : [" + result.getCustomerId() + "]");
System.out.println("✅ [파싱된 Name (15자리)] : [" + result.getName() + "]");
System.out.println("✅ [파싱된 Age (3자리)] : [" + result.getAge() + "]");
System.out.println("==================================================");
assertNotNull(result);
assertEquals("CUST000001", result.getCustomerId());
assertEquals("KIM SHINHAN", result.getName());
assertEquals(35, result.getAge());
}
}