import org.gradle.api.artifacts.DependencyResolveDetails apply from: "build-version.gradle" def isFrontendProject(currentDir){ return file(currentDir.getAbsolutePath() + '/package.json').exists() && !file(currentDir.getAbsolutePath() + '/webpack.env.lib.cjs').exists(); } /*********************************************************************** * gradle 插件 **********************************************************************/ buildscript { repositories { maven { allowInsecureProtocol = true url "${repository_url}" } } dependencies { classpath "org.springframework.boot:org.springframework.boot.gradle.plugin:${spring_boot_version}" classpath "io.sc:io.sc.platform.gradle:${platform_plugin_version}" classpath "org.asciidoctor:asciidoctor-gradle-jvm:${asciidoctor_version}" classpath "com.google.cloud.tools:jib-gradle-plugin:${jib_version}" } } /*********************************************************************** * 所有项目(根项目及其子项目)都应用的插件 **********************************************************************/ allprojects { apply plugin: 'idea' apply plugin: 'io.sc.platform.gradle' } /*********************************************************************** * 所有子项目应用的插件 **********************************************************************/ subprojects { apply plugin: 'java' apply plugin: 'java-library' apply plugin: 'eclipse' apply plugin: 'maven-publish' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' apply plugin: "org.asciidoctor.jvm.convert" configurations.all { //设置 gradle 拉取依赖包的缓存策略为不进行缓存,可保证每次拉取最新的依赖包 //resolutionStrategy.cacheDynamicVersionsFor 0, 'seconds' //动态版本: 1.1.+ //resolutionStrategy.cacheChangingModulesFor 0, 'seconds' //静态版本: 1.1.2 //排除不需要的外部依赖 // exclude group: "org.apache.logging.log4j", module: "log4j-api" // exclude group: "org.apache.logging.log4j", module: "log4j-to-slf4j" // exclude group: "org.slf4j", module: "slf4j-jdk14" exclude group: "org.slf4j", module: "slf4j-nop" resolutionStrategy.eachDependency { DependencyResolveDetails detail -> def requested =detail.requested; def groupAndName =requested.group + ":" + requested.name; if(PlatformDependencyVersions[groupAndName]!=null){ detail.useVersion(PlatformDependencyVersions[groupAndName]); } } } dependencyManagement { resolutionStrategy { //设置 gradle 拉取依赖包的缓存策略为不进行缓存,可保证每次拉取最新的依赖包 //cacheDynamicVersionsFor 0, 'seconds' //动态版本: 1.1.+ //cacheChangingModulesFor 0, 'seconds' //静态版本: 1.1.2 } imports { //mavenBom "org.springframework.cloud:spring-cloud-dependencies:${spring_cloud_version}" mavenBom "com.alibaba.cloud:spring-cloud-alibaba-dependencies:${spring_cloud_alibaba_version}" mavenBom "org.springframework.statemachine:spring-statemachine-bom:${spring_statemachine_version}" } } /*----------------------------------------------------------------- * 配置构建时所需依赖的仓库 url * 将仓库 url 都定位到 ${repository_url} 指定的本地私有仓库地址 *----------------------------------------------------------------*/ repositories { all { ArtifactRepository repo -> if(repo instanceof MavenArtifactRepository){ def url = repo.url.toString() if ( url.startsWith('https://repo1.maven.org/maven2') || url.startsWith('https://jcenter.bintray.com/') || url.startsWith('https://maven.aliyun.com') ) { remove repo } } } maven { allowInsecureProtocol = true url "${repository_url}" } } /*----------------------------------------------------------------- * java 编译时选项 *----------------------------------------------------------------*/ sourceCompatibility ="${java_version}" targetCompatibility ="${java_version}" compileJava.options.encoding ="${java_encoding}" compileTestJava.options.encoding ="${java_encoding}" tasks.withType(JavaCompile) { options.compilerArgs += ["-Xlint:deprecation","-Xlint:unchecked"] } /*----------------------------------------------------------------- * 配置项目基本信息 *----------------------------------------------------------------*/ group ="${application_group}" version ="${application_version}" if(file('package.json').exists()){ mkdir 'java-src/main/java'; mkdir 'java-src/main/resources'; mkdir 'dist'; sourceSets.main.java.srcDir 'java-src/main/java' sourceSets.main.resources.srcDir 'java-src/main/resources' sourceSets.main.resources.srcDir 'dist' } /*----------------------------------------------------------------- * 源代码打包配置 *----------------------------------------------------------------*/ task sourcesJar (type : Jar) { from sourceSets.main.allJava archiveClassifier = 'sources' } /*----------------------------------------------------------------- * Java 文档打包配置 *----------------------------------------------------------------*/ javadoc { options.encoding = 'UTF-8' // 为了能够尽量规范 java doc 文档编写, 指定如果 java doc 中有错误,会报错,并且无法发布到仓库中 failOnError=false } task javadocJar (type: Jar) { from javadoc archiveClassifier = 'javadoc' } clean { delete 'dist' //删除前端自动生成的资源目录 delete 'bin' //删除 eclipse 编译的 bin 目录 delete 'build' //删除 gradle 构建目录 } /*----------------------------------------------------------------- * 配置 eclipse 插件 *----------------------------------------------------------------*/ eclipse{ jdt{ sourceCompatibility ="${java_version}" targetCompatibility ="${java_version}" } } /*----------------------------------------------------------------- * springboot 插件配置 *----------------------------------------------------------------*/ jar { //可以生成普通的 jar enabled = true archiveClassifier.set("") manifest { attributes 'Manifest-Version' : '1.0', 'Implementation-Title' : name, 'Implementation-Vendor' : group, 'Implementation-Version': archiveVersion } } /*----------------------------------------------------------------- * asciidoctor 插件配置,用于生成 asciidoc 文档,用于打包到 jar 中 *----------------------------------------------------------------*/ asciidoctor { baseDirFollowsSourceDir() outputs.upToDateWhen { true } logDocuments = true sourceDir = file('asciidoc') sources { include '*.adoc' } outputDir = file("dist/help/" + project.name) resources { from(sourceDir) { include 'resources/**' } } } asciidoctorj { modules { diagram.use() } } /*----------------------------------------------------------------- * 自定义任务,用于生成 asciidoc 文档到 web 服务器,以便实时查看效果 *----------------------------------------------------------------*/ task doc(type: org.asciidoctor.gradle.jvm.AsciidoctorTask){ baseDirFollowsSourceDir() outputs.upToDateWhen { true } logDocuments = true sourceDir = file('asciidoc') sources { include '*.adoc' } outputDir = file("$asciidoc_deploy_dir" + project.name) // 拷贝 asciidoc 自定义资源 // 设置方式: 通过命令行 -D 传入目标环境参数 // gradle doc -DdocResource=true # 需要拷贝自定义资源 // gradle doc -DdocResource=false # 不需要拷贝自定义资源 def docResource =System.getProperty("docResource")?:"true"; if(docResource=="true"){ resources { from(sourceDir) { include 'resources/**' } } } } /*----------------------------------------------------------------- * 资源处理前执行 asciidoctor *----------------------------------------------------------------*/ processResources { dependsOn asciidoctor doLast{ //打包时移除 jrebel 相关的文件 delete "$buildDir/resources/main/rebel.xml" } } /*----------------------------------------------------------------- * 用于自动生成 jrebel.xml 文件的自定义任务(eclipse) *----------------------------------------------------------------*/ task jrebelEclipse() {} tasks.jrebelEclipse.doLast { File resourcesFile =file('src/main/resources') if(resourcesFile!=null && resourcesFile.exists()){ File rebelFile = file('src/main/resources/rebel.xml') rebelFile.withWriter('UTF-8') { writer -> writer.write('\n'); writer.write('\n'); writer.write('\t\n'); if(file(project.name + '/src/main').exists()){ writer.write('\t\t\n'); } if(file(project.name + '/src/generated').exists()){ writer.write('\t\t\n'); } writer.write('\t\n'); writer.write(''); } } } /*----------------------------------------------------------------- * 用于自动生成 jrebel.xml 文件的自定义任务(idea) *----------------------------------------------------------------*/ task jrebelIdea() {} tasks.jrebelIdea.doLast { if(isFrontendProject(file('.'))) { File resourcesFile = file('java-src/main/resources') if (resourcesFile != null && resourcesFile.exists()) { File rebelFile = file('java-src/main/resources/rebel.xml') rebelFile.withWriter('UTF-8') { writer -> writer.write('\n'); writer.write('\n'); writer.write('\t\n'); if (file(project.name + '/java-src/main').exists()) { writer.write('\t\t\n'); } writer.write('\t\n'); writer.write(''); } } }else { File resourcesFile = file('src/main/resources') if (resourcesFile != null && resourcesFile.exists()) { File rebelFile = file('src/main/resources/rebel.xml') rebelFile.withWriter('UTF-8') { writer -> writer.write('\n'); writer.write('\n'); writer.write('\t\n'); if (file(project.name + '/src/main').exists()) { writer.write('\t\t\n'); } writer.write('\t\n'); writer.write(''); } } } } /*----------------------------------------------------------------- * maven publish 插件配置 *----------------------------------------------------------------*/ publishing { repositories { maven { allowInsecureProtocol = true //允许采用 http 协议发布 url = version.contains('SNAPSHOT') ? "${repository_snapshot_url}" : "${repository_release_url}" credentials { username = (version.contains('SNAPSHOT') ? "${repository_snapshot_username}" : "${repository_release_username}") password = (version.contains('SNAPSHOT') ? "${repository_snapshot_password}" : "${repository_release_password}") } } } publications{ publication(MavenPublication){ from components.java //artifact sourcesJar //artifact javadocJar versionMapping { usage('java-api') { fromResolutionOf('runtimeClasspath') } usage('java-runtime') { fromResolutionResult() } } } } } /*----------------------------------------------------------------- * 更新前端模块的 package.json 文件,同步其中的 name 和 version *----------------------------------------------------------------*/ task frontendUpdatePackageJson(){} tasks.frontendUpdatePackageJson.doFirst { if(isFrontendProject(file('.'))) { println '开始执行 frontendUpdatePackageJson ......' } } tasks.frontendUpdatePackageJson.doLast { if(isFrontendProject(file('.'))){ String content =file('package.json').text; def packageJson = new groovy.json.JsonSlurper().parseText(content); if(packageJson!=null){ println packageJson.dependencies; packageJson.name =project.name; packageJson.version =project.version; packageJson.dependencies['platform-core']=platform_core_frontend_version; def json = groovy.json.JsonOutput.toJson(packageJson); file('package.json').withWriter('UTF-8') { writer -> writer.write(groovy.json.JsonOutput.prettyPrint(json)); } } } } /*----------------------------------------------------------------- * pnpm install *----------------------------------------------------------------*/ task frontendNpmInstall(type:Exec){ if(isFrontendProject(file('.'))){ workingDir '.' if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ commandLine 'cmd', '/c', 'pnpm', 'install' }else{ commandLine 'pnpm', 'install' } }else{ if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ commandLine 'cmd', '/c', 'cd', '.' }else{ commandLine 'cd', '.' } } } tasks.frontendNpmInstall.doFirst { if(isFrontendProject(file('.'))) { println '开始执行 pnpm install ......'; } } /*----------------------------------------------------------------- * pnpm sync *----------------------------------------------------------------*/ task frontendNpmSync(type:Exec){ if(isFrontendProject(file('.')) && !project.name.contains("io.sc.platform.security.frontend")){ workingDir '.' if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ commandLine 'cmd', '/c', 'pnpm', 'sync' }else{ commandLine 'pnpm', 'sync' } }else{ if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ commandLine 'cmd', '/c', 'cd', '.' }else{ commandLine 'cd', '.' } } } tasks.frontendNpmSync.doFirst { if(isFrontendProject(file('.'))) { println '开始执行 pnpm sync ......'; } } /*----------------------------------------------------------------- * pnpm run build *----------------------------------------------------------------*/ task frontendNpmBuild(type:Exec) { if(isFrontendProject(file('.'))){ workingDir '.' if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ commandLine 'cmd', '/c', 'pnpm', 'run', 'build' }else{ commandLine 'pnpm', 'run', 'build' } }else{ if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ commandLine 'cmd', '/c', 'cd', '.' }else{ commandLine 'cd', '.' } } } tasks.frontendNpmBuild.doFirst { if (isFrontendProject(file('.'))) { println '开始执行 pnpm run build ......' } } /*----------------------------------------------------------------- * pnpm run prod *----------------------------------------------------------------*/ task frontendNpmProd(type:Exec) { if(isFrontendProject(file('.'))){ workingDir '.' if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ commandLine 'cmd', '/c', 'pnpm', 'run', 'prod' }else{ commandLine 'pnpm', 'run', 'prod' } }else{ if(org.gradle.internal.os.OperatingSystem.current().isWindows()){ commandLine 'cmd', '/c', 'cd', '.' }else{ commandLine 'cd', '.' } } } tasks.frontendNpmProd.doFirst { if(isFrontendProject(file('.'))){ println '开始执行 pnpm run prod ......' } } /*----------------------------------------------------------------- * 将入口前端 dist/public/模块名 目录下 index.html 文件复制到 classpath:/templates/模块名.html * 提供给 thymeleaf 作为视图模板使用 *----------------------------------------------------------------*/ task frontendGenerateThymeleafTemplate {} tasks.frontendGenerateThymeleafTemplate.doFirst { if(isFrontendProject(file('.'))) { println '开始执行 frontendGenerateThymeleafTemplate ......' delete "java-src/main/resources/templates" mkdir "java-src/main/resources/templates" } } tasks.frontendGenerateThymeleafTemplate.doLast { if(isFrontendProject(file('.'))) { def content = file("dist/public/${project.name}/index.html").text; content = content.replace('