plugins { id 'java' id 'org.springframework.boot' version '3.5.11' id 'io.spring.dependency-management' version '1.1.7' } // LF 줄바꿈, 후행 공백, 파일 끝 개행, 미사용 import 검사는 CodeStyleContractTest가 소유한다. // 이전에는 Spotless 플러그인이 했지만, plugins 블록의 플러그인은 빌드를 읽는 시점에 // 외부 저장소에서 내려받아야 해서 폐쇄망에서는 검사 하나 때문에 빌드 전체가 시작되지 못한다. // 규칙을 테스트로 옮겨 외부 의존성 없이 같은 것을 지킨다. def configureIdeaFormatter = { Exec task, boolean dryRun -> task.group = 'formatting' task.inputs.files(fileTree('src/main/java'), fileTree('src/test/java')) task.inputs.file('.idea/codeStyles/Project.xml') // The IntelliJ formatter is an external binary, so it cannot be a hard build dependency: // CI agents and the closed-network build host may not have the IDE installed. Skip with a // loud warning instead of failing, so `check` still runs CodeStyleContractTest, which owns // the checks that need no tooling (line endings, trailing whitespace, final newline, unused imports). task.onlyIf { if (System.getenv('IDEA_FORMATTER')) { return true } task.logger.warn( "[{}] SKIPPED: IDEA_FORMATTER is not set, so indentation and wrapping are NOT verified. " + "Set it to IntelliJ IDEA's bin/format.bat (Windows) or bin/format.sh to enable this check.", task.name) false } task.doFirst { def formatter = System.getenv('IDEA_FORMATTER') def formatterHome = layout.buildDirectory.dir('idea-formatter').get().asFile formatterHome.mkdirs() def ideaProperties = new File(formatterHome, 'idea.properties') def normalizedHome = formatterHome.absolutePath.replace('\\', '/') ideaProperties.text = """idea.config.path=${normalizedHome}/config idea.system.path=${normalizedHome}/system idea.log.path=${normalizedHome}/log idea.plugins.path=${normalizedHome}/plugins """ task.environment 'IDEA_PROPERTIES', ideaProperties.absolutePath def arguments = ['-s', file('.idea/codeStyles/Project.xml').absolutePath, '-charset', 'UTF-8'] if (dryRun) { arguments << '-d' } arguments.addAll(['-r', file('src/main/java').absolutePath, file('src/test/java').absolutePath]) if (System.getProperty('os.name').toLowerCase().contains('windows')) { task.commandLine(['cmd', '/c', formatter] + arguments) } else { task.commandLine([formatter] + arguments) } } } tasks.register('ideaFormat', Exec) { description = 'Formats all Java sources with the IntelliJ IDEA project code style.' configureIdeaFormatter(delegate, false) } tasks.register('ideaFormatCheck', Exec) { description = 'Checks all Java sources with the IntelliJ IDEA project code style.' configureIdeaFormatter(delegate, true) } // `check`는 `test`를 이미 포함하므로 CodeStyleContractTest가 함께 돈다. // 여기에 IntelliJ 포맷터 검사를 붙여, 검증 명령 하나로 서식과 동작을 모두 확인한다. tasks.named('check') { dependsOn 'ideaFormatCheck' } group = 'io.shinhanlife.dat.biz.mcp' version = '0.1.0' java { toolchain { languageVersion = JavaLanguageVersion.of(21) } } repositories { mavenCentral() } dependencies { // This module supplies the MCP protocol models transitively and the Jackson 2 schema validator directly. // The MCP server starter/transport is intentionally excluded because this project owns the /mcp HTTP contract. implementation 'io.modelcontextprotocol.sdk:mcp-json-jackson2:2.0.0' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-data-redis' implementation 'org.springframework.boot:spring-boot-starter-actuator' annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'com.squareup.okhttp3:mockwebserver:4.12.0' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } tasks.named('test') { useJUnitPlatform() } tasks.withType(JavaCompile).configureEach { options.compilerArgs += ['-Xlint:deprecation', '-Xlint:unchecked'] } tasks.named('bootJar') { archiveFileName = 'ax-hub-mcp-server.jar' }