plugins { id 'java' id 'org.springframework.boot' version '3.3.6' id 'io.spring.dependency-management' version '1.1.7' } group = 'ru.shine' version = '0.1.0' java { toolchain { languageVersion = JavaLanguageVersion.of(21) } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'com.mmorrell:solanaj:1.20.4' testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('test') { useJUnitPlatform() } tasks.named('bootJar') { archiveFileName = 'SHiNE-promo-solana-devnet.jar' } // ------------------------------------------------------------ // ДЕПЛОЙ ВРЕМЕННОГО СЕРВИСА "SHiNE-promo-solana-devnet" // // Назначение сервиса: // - это отдельный продукт для тестовой раздачи SOL в devnet; // - нужен для упрощённого онбординга тестовых пользователей; // - работает как самостоятельное Spring Boot приложение. // // Почему отдельный деплой: // - сервис изолирован от основного SHiNE-сервера; // - его можно обновлять/перезапускать независимо; // - жизненный цикл временного сервиса не должен ломать основной прод. // // ВАЖНО: // - деплой по умолчанию выполняется ЧЕРЕЗ ДОМЕН (shineup.me), а не по IP; // - целевая папка на сервере: /home/player/SHiNE/SHiNE-promo-solana-devnet; // - целевой systemd-сервис: SHiNE-promo-solana-devnet. // ------------------------------------------------------------ def deployHost = project.findProperty('deployHost') ?: 'root@shineup.me' def deployPath = project.findProperty('deployPath') ?: '/home/player/SHiNE/SHiNE-promo-solana-devnet' def remoteServiceName = project.findProperty('deployService') ?: 'SHiNE-promo-solana-devnet' tasks.register('buildServerBundle', Copy) { // Сборка минимального серверного бандла: // 1) fat-jar приложения // 2) шаблон application.properties (чтобы был эталон конфигурации) dependsOn tasks.named('bootJar') from(tasks.named('bootJar').flatMap { it.archiveFile }) { rename { 'SHiNE-promo-solana-devnet.jar' } } from('config/application.example.properties') { rename { 'application.properties' } } into(layout.buildDirectory.dir('server-bundle')) } tasks.register('deployToServerMkdir', Exec) { // Шаг 1: гарантируем существование целевой директории на удалённом сервере. dependsOn tasks.named('buildServerBundle') commandLine 'bash', '-lc', "ssh ${deployHost} 'mkdir -p ${deployPath}'" } tasks.register('deployToServerJar', Exec) { // Шаг 2: загружаем исполняемый jar. dependsOn tasks.named('deployToServerMkdir') commandLine 'bash', '-lc', "scp ${layout.buildDirectory.file('server-bundle/SHiNE-promo-solana-devnet.jar').get().asFile.absolutePath} ${deployHost}:${deployPath}/" } tasks.register('deployToServerConfig', Exec) { // Шаг 3: загружаем конфиг-шаблон. // На проде при необходимости его можно заменить на рабочий конфиг с секретами. dependsOn tasks.named('deployToServerJar') commandLine 'bash', '-lc', "scp ${layout.buildDirectory.file('server-bundle/application.properties').get().asFile.absolutePath} ${deployHost}:${deployPath}/" } tasks.register('deployToServerRestart', Exec) { // Шаг 4: перезапускаем systemd-сервис и показываем статус. // Если сервис не поднялся, ошибка будет видна сразу в этом шаге. dependsOn tasks.named('deployToServerConfig') commandLine 'bash', '-lc', "ssh ${deployHost} 'sudo systemctl restart ${remoteServiceName} && sudo systemctl --no-pager status ${remoteServiceName}'" } tasks.register('deployToServer') { // Единая точка входа для деплоя временного сервиса. // Запуск: ./gradlew deployToServer dependsOn tasks.named('deployToServerRestart') }