Skip to content

Commit

Permalink
Merge pull request #375 from jdaugherty/7.0.x
Browse files Browse the repository at this point in the history
End to End testing for the publish plugin & clean-up of previously failed changes
  • Loading branch information
jdaugherty authored Dec 19, 2024
2 parents bc3e7cf + 506e3b9 commit a195d18
Show file tree
Hide file tree
Showing 73 changed files with 1,533 additions and 34 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
DEVELOCITY_BUILD_CACHE_NODE_KEY: ${{ secrets.GRADLE_ENTERPRISE_BUILD_CACHE_NODE_KEY }}
run: ./gradlew build
publish:
if: github.event_name == 'push'
if: github.event_name == 'push' && github.repository_owner == 'grails'
needs: ['build']
runs-on: ubuntu-latest
steps:
Expand All @@ -59,7 +59,7 @@ jobs:
-Dorg.gradle.internal.publish.checksums.insecure=true
publish
docs:
if: github.event_name == 'push'
if: github.event_name == 'push' && github.repository_owner == 'grails'
needs: publish
runs-on: ubuntu-latest
permissions:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/release-notes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ on:
workflow_dispatch:
jobs:
release_notes:
if: github.event_name == 'push' && github.repository_owner == 'grails'
permissions:
contents: read
runs-on: ubuntu-latest
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ The credentials and connection url must be specified as a project property or an
NEXUS_PUBLISH_SNAPSHOT_URL
NEXUS_PUBLISH_STAGING_PROFILE_ID

By default, the release or snapshot state is determined by the project.version or projectVersion gradle property. To override this behavior, use the environment variable `GRAILS_PUBLISH_RELEASE` to decide if it's a release or snapshot.

grails-web
---------
* Adds web specific extensions
Expand Down
32 changes: 26 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,30 @@ dependencies {
// compile grails-gradle-plugin with the Groovy version provided by Gradle
// to ensure build compatibility with Gradle, currently Groovy 3.0.x
// see: https://docs.gradle.org/current/userguide/compatibility.html#groovy
compileOnly "org.codehaus.groovy:groovy:$GroovySystem.version"
compileOnly "org.codehaus.groovy:groovy:$GroovySystem.version"
compileOnly "org.grails:grails-bootstrap:$grailsVersion", {
exclude group: 'org.apache.groovy'
exclude group: 'org.spockframework'
}
compileOnly "org.grails:grails-shell:$grailsShellVersion", {
exclude group: 'org.apache.groovy'
exclude group: 'org.spockframework'
}

runtimeOnly "org.grails:grails-bootstrap:$grailsVersion"
runtimeOnly "org.grails:grails-shell:$grailsShellVersion"
runtimeOnly "org.grails:grails-bootstrap:$grailsVersion", {
exclude group: 'org.apache.groovy'
exclude group: 'org.spockframework'
}
runtimeOnly "org.grails:grails-shell:$grailsShellVersion", {
exclude group: 'org.apache.groovy'
exclude group: 'org.spockframework'
}

implementation "org.grails:grails-gradle-model:$grailsVersion", {
exclude group: 'org.apache.groovy'
exclude group: 'org.spockframework'
}

implementation "org.grails:grails-gradle-model:$grailsVersion"

implementation "io.github.gradle-nexus:publish-plugin:$gradleNexusPublishPluginVersion"
implementation "com.bmuschko:gradle-nexus-plugin:$gradleNexusPluginVersion"
implementation "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
Expand Down Expand Up @@ -238,6 +249,14 @@ publishing {
}
}

// publishAllPublicationsToTestCaseMavenRepoRepository
repositories {
maven {
name = "TestCaseMavenRepo"
url = layout.buildDirectory.dir('local-maven')
}
}

publications {
pluginMaven(MavenPublication) {
pom {
Expand Down Expand Up @@ -280,7 +299,7 @@ publishing {
}

project.afterEvaluate {
project.publishing.publications.each { MavenPublication publication->
project.publishing.publications.each { MavenPublication publication ->
if (publication.name != "pluginMaven") {
publication.pom.withXml {
def xml = asNode()
Expand All @@ -294,3 +313,4 @@ tasks.named("build").configure {
finalizedBy("groovydoc")
}

apply from: rootProject.layout.projectDirectory.file('gradle/e2eTest.gradle')
2 changes: 2 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ grailsVersion=7.0.0-SNAPSHOT
grailsShellVersion=7.0.0-SNAPSHOT
springBootVersion=3.4.0
springGradleDependencyManagementVersion=1.1.6
# Since we're pulling in spring's dependency management, we need to override this to support the groovy version of gradle
spock.version=2.3-groovy-3.0
org.gradle.caching=true
org.gradle.daemon=true
org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Xmx1536M -XX:MaxMetaspaceSize=512M
35 changes: 35 additions & 0 deletions gradle/e2eTest.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
def e2eTest = sourceSets.create('e2eTest')
def e2eTestTask = tasks.register('e2eTest', Test) {
group = 'verification'
testClassesDirs = sourceSets.e2eTest.output.classesDirs
classpath = sourceSets.e2eTest.runtimeClasspath
useJUnitPlatform()
systemProperty("localMavenPath", rootProject.layout.buildDirectory.dir('local-maven').get().asFile.absolutePath)
systemProperty("grailsGradlePluginVersion", rootProject.version)

testLogging {
exceptionFormat = 'full'
events 'passed', 'skipped', 'failed', 'standardOut', 'standardError'
}
beforeTest { descriptor -> logger.quiet " -- $descriptor" }

dependsOn "publishAllPublicationsToTestCaseMavenRepoRepository"
}

tasks.named("check") {
dependsOn e2eTestTask
}

gradlePlugin {
testSourceSets e2eTest
}

dependencies {
// Note: must use a groovy 3 compatible version of Spock
e2eTestImplementation "org.spockframework:spock-core:${project['spock.version']}", {
exclude group: 'org.apache.groovy'
}
e2eTestImplementation 'commons-io:commons-io:2.18.0'
e2eTestImplementation gradleTestKit()
e2eTestRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
130 changes: 130 additions & 0 deletions src/e2eTest/groovy/org/grails/gradle/test/GradleSpecification.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package org.grails.gradle.test

import org.apache.commons.io.FileUtils
import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.BuildTask
import org.gradle.testkit.runner.GradleRunner
import org.gradle.testkit.runner.TaskOutcome
import spock.lang.Specification

import java.nio.file.Files
import java.nio.file.Path

abstract class GradleSpecification extends Specification {
private static Path basePath

private static GradleRunner gradleRunner

void setupSpec() {
basePath = Files.createTempDirectory("gradle-projects")
Path testKitDirectory = Files.createDirectories(basePath.resolve('.gradle'))
gradleRunner = GradleRunner.create()
.withPluginClasspath()
.withTestKitDir(testKitDirectory.toFile())

gradleRunner = addEnvironmentVariable(
"LOCAL_MAVEN_PATH",
System.getProperty("localMavenPath"),
gradleRunner
)

gradleRunner = setGradleProperty(
"grailsGradlePluginVersion",
System.getProperty("grailsGradlePluginVersion"),
gradleRunner
)
}

GradleRunner addEnvironmentVariable(String key, String value, GradleRunner runner) {
Map environment = runner.environment
if (environment) {
environment.put(key, value)

return runner
} else {
return runner.withEnvironment([(key): value])
}
}

GradleRunner setGradleProperty(String key, String value, GradleRunner runner) {
addEnvironmentVariable("ORG_GRADLE_PROJECT_${key}", value, runner)
}

void cleanup() {
basePath.toFile().listFiles().each {
// Reuse the gradle cache from previous tests
if (it.name == ".gradle") {
return
}

FileUtils.deleteQuietly(it)
}
}

void cleanupSpec() {
FileUtils.deleteQuietly(basePath.toFile())
}

protected GradleRunner setupTestResourceProject(String type, String projectName, String nestedProject = null) {
Objects.requireNonNull(projectName, "projectName must not be null")

Path destinationDir = basePath.resolve(type)
Files.createDirectories(destinationDir)

Path sourceProjectDir = Path.of("src/e2eTest/resources/publish-projects/$type/$projectName")
FileUtils.copyDirectoryToDirectory(sourceProjectDir.toFile(), destinationDir.toFile())

setupProject(destinationDir.resolve(projectName).resolve(nestedProject ?: '.'))
}

protected GradleRunner setupProject(Path projectDirectory) {
gradleRunner.withProjectDir(projectDirectory.toFile())
}

protected Path createProjectDir(String projectName) {
Objects.requireNonNull(projectName, "projectName must not be null")

Path destinationDir = basePath.resolve(projectName)
Files.createDirectories(destinationDir)

destinationDir
}

protected BuildResult executeTask(String taskName, List<String> otherArguments = [], GradleRunner gradleRunner) {
List arguments = [taskName, "--stacktrace"]
arguments.addAll(otherArguments)

gradleRunner.withArguments(arguments).forwardOutput().build()
}

protected void assertTaskSuccess(String taskName, BuildResult result) {
def tasks = result.tasks.find { it.path.endsWith(":${taskName}") }
if (!tasks) {
throw new IllegalStateException("No tasks were found for `${taskName}`")
}

tasks.each { BuildTask task ->
if (task.outcome != TaskOutcome.SUCCESS) {
throw new IllegalStateException("Task $taskName failed with outcome $task.outcome")
}
}
}

protected void assertBuildSuccess(BuildResult result, List<String> ignoreTaskNames = []) {
def results = result.tasks.groupBy { it.outcome }

for (String ignoredTaskName : ignoreTaskNames) {
for (BuildTask ignoredTask : result.tasks.findAll { it.path.endsWith("${ignoredTaskName}") }) {
def taskOutComeTasks = results.get(ignoredTask.outcome)
taskOutComeTasks.remove(ignoredTask)
if (!taskOutComeTasks) {
results.remove(ignoredTask.outcome)
}
}
}

if (results.keySet().size() != 1) {
throw new IllegalStateException("Unexpected Task failures: ${results.findAll { it.key != TaskOutcome.SUCCESS }}")
}
}
}
Loading

0 comments on commit a195d18

Please sign in to comment.