diff --git a/build.gradle b/build.gradle index 18e480b..6c6163e 100644 --- a/build.gradle +++ b/build.gradle @@ -5,58 +5,118 @@ buildscript { maven { url 'https://repo.gradle.org/gradle/libs-releases' } } dependencies { + classpath "io.github.gradle-nexus:publish-plugin:1.1.0" classpath "org.grails:grails-gradle-plugin:$grailsVersion" - classpath "org.grails:grails-docs:$grailsVersion" + classpath "org.gradle:test-retry-gradle-plugin:1.4.0" + classpath "io.spring.gradle:dependency-management-plugin:$springDependencyManagementPluginVersion" } } -repositories { - mavenLocal() - mavenCentral() - maven { url "https://repo.grails.org/grails/core" } +ext { + isReleaseVersion = !project.projectVersion.endsWith('-SNAPSHOT') + grailsVersion = project.grailsVersion + userOrg = "grails" } -version project.projectVersion +apply plugin:'idea' -ext { - commonBuild = 'https://raw.githubusercontent.com/rainboyan/grails-common-build/23.0.x' +if (isReleaseVersion) { + apply plugin: 'maven-publish' + apply plugin: "io.github.gradle-nexus.publish-plugin" + + nexusPublishing { + repositories { + sonatype { + def ossUser = System.getenv("SONATYPE_USERNAME") ?: project.hasProperty("sonatypeOssUsername") ? project.sonatypeOssUsername : '' + def ossPass = System.getenv("SONATYPE_PASSWORD") ?: project.hasProperty("sonatypeOssPassword") ? project.sonatypeOssPassword : '' + def ossStagingProfileId = System.getenv("SONATYPE_STAGING_PROFILE_ID") ?: project.hasProperty("sonatypeOssStagingProfileId") ? project.sonatypeOssStagingProfileId : '' + nexusUrl = uri("https://s01.oss.sonatype.org/service/local/") + username = ossUser + password = ossPass + stagingProfileId = ossStagingProfileId + } + } + } } -subprojects { +subprojects { project-> + group "org.grails" version project.projectVersion - ext { - userOrg = "grails" - isGrailsPlugin = name.startsWith('grails-plugin') - isBuildSnapshot = version.toString().endsWith("-SNAPSHOT") + if (project.name.startsWith('examples') || project.name.endsWith('docs')) { + return } - if (isGrailsPlugin) { - group "org.grails.plugins" - } - else { - group "org.grails" - } + apply plugin: 'eclipse' + apply plugin: 'idea' + apply plugin: 'java-library' + apply plugin: 'groovy' + apply plugin: 'maven-publish' + apply plugin: 'signing' + apply plugin: "org.gradle.test-retry" + apply plugin: "io.spring.dependency-management" + + sourceCompatibility = 17 + targetCompatibility = 17 repositories { mavenLocal() + mavenCentral() maven { url "https://repo.grails.org/grails/core" } + maven { url 'https://repo.gradle.org/gradle/libs-releases' } } - if (it.projectDir.path.endsWith("examples/${it.name}".toString())) { - apply plugin:"org.grails.grails-web" - } - else if (isGrailsPlugin) { - apply from: resources.text.fromInsecureUri("${commonBuild}/common-plugin.gradle") - } - else { - apply from: resources.text.fromInsecureUri("${commonBuild}/common-project.gradle") + dependencyManagement { + imports { + mavenBom "org.grails:grails-bom:$grailsVersion" + } + applyMavenExclusions false } - dependencies { - compileOnly "jakarta.annotation:jakarta.annotation-api:$jakartaAnnotationVersion" + apply from: '../publishing/grailsCentralPublishing.gradle' + + + if (project.name.startsWith('grails-')) { + configurations { + documentation + } + + dependencies { + api "org.apache.groovy:groovy:$groovyVersion" + api "org.slf4j:slf4j-api:$slf4jVersion" + documentation "org.fusesource.jansi:jansi:$jansiVersion" + documentation "org.codehaus.groovy:groovy-dateutil:$groovyVersion" + documentation "info.picocli:picocli:$picocliVersion" + documentation "com.github.javaparser:javaparser-core:$javaParserCoreVersion" + + testImplementation "org.spockframework:spock-core:$spockVersion" + testImplementation "org.codehaus.groovy:groovy-test-junit5:$groovyVersion" + testImplementation "org.junit.jupiter:junit-jupiter-api:$junitJupiterVersion" + testImplementation "org.junit.platform:junit-platform-runner:$junitJupiterPlatformVersion" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitJupiterVersion" + } + + java { + withJavadocJar() + withSourcesJar() + } + + tasks.withType(Test) { + useJUnitPlatform() + testLogging { + showStandardStreams = true + exceptionFormat = 'full' + } + configure { + retry { + maxRetries = 2 + maxFailures = 20 + failOnPassedAfterRetry = true + } + } + } + + groovydoc.classpath = configurations.documentation } -} -apply from: resources.text.fromInsecureUri("${commonBuild}/common-publishing.gradle") -apply from: resources.text.fromInsecureUri("${commonBuild}/common-docs.gradle") +} diff --git a/gradle.properties b/gradle.properties index 78f8824..ef010f4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,8 +9,15 @@ developers=Graeme Rocher grailsVersion=2023.1.0-M2 groovyVersion=4.0.15 gormVersion=2023.1.0-M1 +hibernateCoreVersion=5.6.15.Final jakartaAnnotationVersion=2.1.1 +jansiVersion=1.18 +javaParserCoreVersion=3.15.14 +junitJupiterVersion=5.8.2 +junitJupiterPlatformVersion=1.8.2 +picocliVersion=4.6.3 servletApiVersion=6.0.0 -spockVersion=2.3-groovy-4.0 slf4jVersion=2.0.9 -hibernateCoreVersion=5.6.15.Final \ No newline at end of file +spockVersion=2.3-groovy-4.0 +springVersion=6.0.12 +springDependencyManagementPluginVersion=1.1.3 diff --git a/grails-plugin-scaffolding/build.gradle b/grails-plugin-scaffolding/build.gradle index 20f9f05..2de8daf 100644 --- a/grails-plugin-scaffolding/build.gradle +++ b/grails-plugin-scaffolding/build.gradle @@ -1,5 +1,6 @@ dependencies { api "org.grails:grails-core:$grailsVersion" + api "org.grails:grails-bootstrap:$grailsVersion" api "org.grails:grails-plugin-rest:$grailsVersion" api "org.grails:grails-web-gsp:$grailsVersion" compileOnly "org.grails:grails-boot:$grailsVersion" diff --git a/grails-plugin-scaffolding/grails-app/conf/application.yml b/grails-plugin-scaffolding/grails-app/conf/application.yml deleted file mode 100644 index b6a6a80..0000000 --- a/grails-plugin-scaffolding/grails-app/conf/application.yml +++ /dev/null @@ -1,13 +0,0 @@ -grails: - profile: plugin - codegen: - defaultPackage: scaffolding -info: - app: - name: '@info.app.name@' - version: '@info.app.version@' - grailsVersion: '@info.app.grailsVersion@' -spring: - groovy: - template: - check-template-location: false diff --git a/grails-plugin-scaffolding/grails-app/init/.keep b/grails-plugin-scaffolding/grails-app/init/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/grails-plugin-scaffolding/src/main/groovy/grails/plugin/scaffolding/ScaffoldingGrailsPlugin.groovy b/grails-plugin-scaffolding/src/main/groovy/grails/plugin/scaffolding/ScaffoldingGrailsPlugin.groovy deleted file mode 100644 index 3a15590..0000000 --- a/grails-plugin-scaffolding/src/main/groovy/grails/plugin/scaffolding/ScaffoldingGrailsPlugin.groovy +++ /dev/null @@ -1,47 +0,0 @@ -package grails.plugin.scaffolding - -import grails.plugins.* -import org.grails.web.servlet.view.GroovyPageViewResolver - -class ScaffoldingGrailsPlugin extends Plugin { - - // the version or versions of Grails the plugin is designed for - def grailsVersion = "5.0.0 > *" - // resources that are excluded from plugin packaging - def pluginExcludes = [ - "grails-app/views/error.gsp" - ] - - def title = "Scaffolding Plugin" // Headline display name of the plugin - def author = "Graeme Rocher" - def authorEmail = "info@grails.org" - def description = '''\ -Plugin that generates scaffolded controllers and views for a Grails application. -''' - - // URL to the plugin's documentation - def documentation = "http://grails.org/plugin/scaffolding" - - // Extra (optional) plugin metadata - - // License: one of 'APACHE', 'GPL2', 'GPL3' - def license = "APACHE" - - - // Location of the plugin's issue tracker. - def issueManagement = [ system: "Github", url: "https://github.com/grails3-plugins/scaffolding/issues" ] - - // Online location of the plugin's browseable source code. - def scm = [ url: "https://github.com/grails3-plugins/scaffolding" ] - - def loadAfter = ["groovyPages"] - - @Override - Closure doWithSpring() { {-> - // Configure a Spring MVC view resolver - jspViewResolver(ScaffoldingViewResolver) { bean -> - bean.lazyInit = true - bean.parent = "abstractViewResolver" - } - }} -} diff --git a/grails-plugin-scaffolding/src/main/groovy/org/grails/plugin/scaffolding/ScaffoldingAutoConfiguration.java b/grails-plugin-scaffolding/src/main/groovy/org/grails/plugin/scaffolding/ScaffoldingAutoConfiguration.java new file mode 100644 index 0000000..903b2fa --- /dev/null +++ b/grails-plugin-scaffolding/src/main/groovy/org/grails/plugin/scaffolding/ScaffoldingAutoConfiguration.java @@ -0,0 +1,63 @@ +package org.grails.plugin.scaffolding; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureOrder; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.util.ClassUtils; + +import grails.config.Config; +import grails.config.Settings; +import grails.core.GrailsApplication; +import grails.plugin.scaffolding.ScaffoldingViewResolver; +import grails.util.Environment; +import org.grails.gsp.GroovyPagesTemplateEngine; +import org.grails.web.gsp.io.GrailsConventionGroovyPageLocator; +import org.grails.web.servlet.view.GroovyPageViewResolver; +import org.grails.web.util.GrailsApplicationAttributes; + +@AutoConfiguration +@AutoConfigureOrder +public class ScaffoldingAutoConfiguration { + + private static final String GSP_RELOAD_INTERVAL = "grails.gsp.reload.interval"; + + @Bean + @Order(-10) + @ConditionalOnMissingBean + public ScaffoldingViewResolver jspViewResolver(ObjectProvider grailsApplication, + ObjectProvider groovyPagesTemplateEngine, + ObjectProvider groovyPageLocator) { + + Config config = grailsApplication.getIfAvailable().getConfig(); + Environment env = Environment.getCurrent(); + boolean developmentMode = Environment.isDevelopmentEnvironmentAvailable(); + boolean gspEnableReload = config.getProperty(Settings.GSP_ENABLE_RELOAD, Boolean.class, false); + boolean enableReload = env.isReloadEnabled() || gspEnableReload || (developmentMode && env == Environment.DEVELOPMENT); + long gspCacheTimeout = config.getProperty(GSP_RELOAD_INTERVAL, Long.class, (developmentMode && env == Environment.DEVELOPMENT) ? 0L : 5000L); + + boolean jstlPresent = ClassUtils.isPresent("javax.servlet.jsp.jstl.core.Config", Thread.currentThread().getContextClassLoader()); + + final ScaffoldingViewResolver scaffoldingViewResolver = new ScaffoldingViewResolver(); + scaffoldingViewResolver.setPrefix(GrailsApplicationAttributes.PATH_TO_VIEWS); + + if (jstlPresent) { + scaffoldingViewResolver.setSuffix(GroovyPageViewResolver.JSP_SUFFIX); + } + else { + scaffoldingViewResolver.setSuffix(GroovyPageViewResolver.GSP_SUFFIX); + } + groovyPagesTemplateEngine.ifAvailable(scaffoldingViewResolver::setTemplateEngine); + groovyPageLocator.ifAvailable(scaffoldingViewResolver::setGroovyPageLocator); + + if (enableReload) { + scaffoldingViewResolver.setCacheTimeout(gspCacheTimeout); + } + scaffoldingViewResolver.setOrder(Ordered.LOWEST_PRECEDENCE - 100); + return scaffoldingViewResolver; + } + +} diff --git a/grails-plugin-scaffolding/src/main/resources/META-INF/grails.factories b/grails-plugin-scaffolding/src/main/resources/META-INF/grails.factories new file mode 100644 index 0000000..fffe16e --- /dev/null +++ b/grails-plugin-scaffolding/src/main/resources/META-INF/grails.factories @@ -0,0 +1,2 @@ +grails.compiler.ast.ClassInjector=\ +org.grails.compiler.scaffolding.ScaffoldingControllerInjector \ No newline at end of file diff --git a/grails-plugin-scaffolding/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/grails-plugin-scaffolding/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..2d02677 --- /dev/null +++ b/grails-plugin-scaffolding/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.grails.plugin.scaffolding.ScaffoldingAutoConfiguration \ No newline at end of file diff --git a/publishing/grailsCentralPublishing.gradle b/publishing/grailsCentralPublishing.gradle new file mode 100644 index 0000000..d9c87bf --- /dev/null +++ b/publishing/grailsCentralPublishing.gradle @@ -0,0 +1,108 @@ +ext."signing.keyId" = rootProject.hasProperty("signing.keyId") ? rootProject.getProperty('signing.keyId') : System.getenv('SIGNING_KEY') +ext."signing.password" = rootProject.hasProperty("signing.password") ? rootProject.getProperty('signing.password') : System.getenv('SIGNING_PASSPHRASE') +ext."signing.secretKeyRingFile" = rootProject.hasProperty("signing.secretKeyRingFile") ? rootProject.getProperty('signing.secretKeyRingFile') : "${System.properties['user.home']}${File.separator}.gnupg${File.separator}secring.gpg" + +ext.pomInfo = { + delegate.url 'https://github.com/grails/scaffolding' + delegate.licenses { + delegate.license { + delegate.name 'The Apache Software License, Version 2.0' + delegate.url 'https://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + delegate.scm { + delegate.url 'https://github.com/grails/scaffolding' + delegate.connection 'scm:git:git://github.com/grails/grails-scaffolding' + delegate.developerConnection 'scm:git:ssh://github.com:grails/grails-scaffolding' + } + delegate.developers { + delegate.developer { + delegate.id 'graemerocher' + delegate.name 'Graeme Rocher' + delegate.email 'graeme.rocher@gmail.com' + } + developer { + delegate.id 'rainboyan' + delegate.name 'Michael Yan' + delegate.email 'rain@rainboyan.com' + } + } +} + +publishing { + publications { + maven(MavenPublication) { + artifactId project.name + from components.java + + pom { + name = 'Grails Scaffolding' + description = 'Plugin that generates scaffolded controllers and views for a Grails application.' + } + + pom.withXml { + def pomNode = asNode() + pomNode.children().last() + pomInfo + try { + pomNode.dependencyManagement.replaceNode {} + } catch (Throwable e) { + // ignore + } + + // simply remove dependencies without a version + // version-less dependencies are handled with dependencyManagement + // see https://github.com/spring-gradle-plugins/dependency-management-plugin/issues/8 for more complete solutions + pomNode.dependencies.dependency.findAll { + it.version.text().isEmpty() + }.each { + try { + it.replaceNode {} + } catch (Throwable e) { + // ignore + } + } + } + } + } + + if (version.endsWith('-SNAPSHOT')) { + repositories { + maven { + credentials { + username System.getenv('ARTIFACTORY_USERNAME') ?: rootProject.properties.get('artifactoryUsername') + password System.getenv("ARTIFACTORY_PASSWORD") ?: rootProject.properties.get('artifactoryPassword') + } + + if (group == 'org.grails.plugins') { + url "https://repo.grails.org/grails/plugins3-snapshots-local" + } else { + url "https://repo.grails.org/grails/libs-snapshots-local" + } + } + } + } +} + +jar { + manifest.mainAttributes( + "Built-By": System.properties['user.name'], + "Created-By": System.properties['java.vm.version'] + " (" + System.properties['java.vm.vendor'] + ")", + "Implementation-Title": "Grails", + "Implementation-Version": grailsVersion, + "Implementation-Vendor": 'grails.org') +} + +afterEvaluate { + signing { + required { isReleaseVersion && gradle.taskGraph.hasTask("publish") } + Publication[] publications = new Publication[project.publishing.publications.size()] + project.publishing.publications.findAll().toArray(publications) + sign(publications) + } + + tasks.withType(Sign) { + onlyIf { isReleaseVersion } + } +} + +task install(dependsOn: project.tasks.withType(PublishToMavenLocal))