diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a1ea77d..5ba91b58 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,29 +17,24 @@ jobs: matrix: os: [ubuntu-latest, windows-latest] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK 11 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: "11" distribution: "temurin" - - name: Cache Dependencies - uses: actions/cache@v3 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }} - restore-keys: ${{ runner.os }}-gradle + cache: "gradle" - name: Build run: ./gradlew clean build testGradle8.4 - - name: Archive Codenarc Report - uses: actions/upload-artifact@v3 - if: ${{ always() }} + - name: Archive Codenarc Report on Failure + uses: actions/upload-artifact@v4 + if: ${{ failure() }} with: name: codenarc-results path: build/reports/codenarc - - name: Archive Test Results - uses: actions/upload-artifact@v3 - if: ${{ always() }} + - name: Archive Test Results on Failure + uses: actions/upload-artifact@v4 + if: ${{ failure() }} with: - name: test-results + name: ${{ matrix.os }}-ci-test-results path: build/reports/tests diff --git a/.github/workflows/regression.yml b/.github/workflows/regression.yml index e26a94e6..4fef674f 100644 --- a/.github/workflows/regression.yml +++ b/.github/workflows/regression.yml @@ -19,23 +19,18 @@ jobs: os: [ubuntu-latest, windows-latest] gradle_version: ["7.1.1", "8.0.2"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK 11 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: "11" distribution: "temurin" - - name: Cache Dependencies - uses: actions/cache@v3 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }} - restore-keys: ${{ runner.os }}-gradle + cache: "gradle" - name: Test ${{ matrix.gradle_version }} run: ./gradlew testGradle${{ matrix.gradle_version }} - - name: Archive Test Results - uses: actions/upload-artifact@v3 - if: ${{ always() }} + - name: Archive Test Results on Failure + uses: actions/upload-artifact@v4 + if: ${{ failure() }} with: - name: test-results + name: ${{ matrix.os }}-${{ matrix.gradle_version }}-test-results path: build/reports/tests diff --git a/build.gradle.kts b/build.gradle.kts index 00b8b7d4..4cf65c30 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,7 @@ import okio.buffer import okio.sink import org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL +import org.gradle.api.tasks.testing.logging.TestLogEvent import java.nio.file.StandardOpenOption buildscript { @@ -149,9 +150,13 @@ tasks.addRule("Pattern: testGradle") { } } +val isCi = providers.environmentVariable("CI") tasks.withType().configureEach { useJUnitPlatform() testLogging { + if (isCi.map { it.toBoolean() }.getOrElse(false)) { + events(TestLogEvent.FAILED, TestLogEvent.PASSED, TestLogEvent.SKIPPED) + } exceptionFormat = FULL } } diff --git a/src/main/java/org/jenkinsci/gradle/plugins/jpi/internal/DependencyLookup.java b/src/main/java/org/jenkinsci/gradle/plugins/jpi/internal/DependencyLookup.java index 64a674e8..68159696 100644 --- a/src/main/java/org/jenkinsci/gradle/plugins/jpi/internal/DependencyLookup.java +++ b/src/main/java/org/jenkinsci/gradle/plugins/jpi/internal/DependencyLookup.java @@ -45,7 +45,7 @@ public Set find(String configuration, String jenkinsVersion) deps.add(testHarness); return deps; case "declaredJenkinsWar": - deps.add(new MavenDependency("org.jenkins-ci.main:jenkins-war:" + jenkinsVersion + "@war")); + deps.add(new MavenDependency("org.jenkins-ci.main:jenkins-war:" + jenkinsVersion)); return deps; } return deps; diff --git a/src/main/kotlin/org/jenkinsci/gradle/plugins/testing/JpiTestingPlugin.kt b/src/main/kotlin/org/jenkinsci/gradle/plugins/testing/JpiTestingPlugin.kt index d92c6b56..df8a79a3 100644 --- a/src/main/kotlin/org/jenkinsci/gradle/plugins/testing/JpiTestingPlugin.kt +++ b/src/main/kotlin/org/jenkinsci/gradle/plugins/testing/JpiTestingPlugin.kt @@ -19,8 +19,6 @@ open class JpiTestingPlugin : Plugin { companion object { fun Test.useJenkinsRule(dir: Provider) { doFirst { - val war = project.configurations.getByName("declaredJenkinsWar").resolvedConfiguration.resolvedArtifacts.single() - systemProperty("jth.jenkins-war.path", war.file.absolutePath) systemProperty("java.awt.headless", "true") // set build directory for Jenkins test harness, JENKINS-26331 // this is the directory the war will be exploded to @@ -29,7 +27,7 @@ open class JpiTestingPlugin : Plugin { } } override fun apply(target: Project) { - target.configurations.create("declaredJenkinsWar") { + val declaredJenkinsWar = target.configurations.create("declaredJenkinsWar") { isVisible = false isCanBeConsumed = false isCanBeResolved = true @@ -109,6 +107,9 @@ open class JpiTestingPlugin : Plugin { testClassesDirs = generatedSourceSet.output.classesDirs classpath = project.files(generatedJenkinsPluginsDir.get().asFile.parentFile) + generatedSourceSet.runtimeClasspath } + target.configurations.getByName("generatedJenkinsTestRuntimeOnly") { + extendsFrom(declaredJenkinsWar) + } target.tasks.named("check").configure { dependsOn(generatedJenkinsTest) } @@ -128,5 +129,8 @@ open class JpiTestingPlugin : Plugin { inputs.files(copyPluginsForTest) classpath += project.files(testPluginsDir.get().asFile.parentFile) } + target.configurations.getByName("testRuntimeOnly") { + extendsFrom(declaredJenkinsWar) + } } } diff --git a/src/test/groovy/org/jenkinsci/gradle/plugins/jpi/JpiPublishingAndConsumptionTest.groovy b/src/test/groovy/org/jenkinsci/gradle/plugins/jpi/JpiPublishingAndConsumptionTest.groovy index 03d6c541..4b2ccab4 100644 --- a/src/test/groovy/org/jenkinsci/gradle/plugins/jpi/JpiPublishingAndConsumptionTest.groovy +++ b/src/test/groovy/org/jenkinsci/gradle/plugins/jpi/JpiPublishingAndConsumptionTest.groovy @@ -85,7 +85,7 @@ class JpiPublishingAndConsumptionTest extends IntegrationSpec { when: consumerBuild << """ jenkinsPlugin { - jenkinsVersion = '1.580.1' + jenkinsVersion = '${TestSupport.RECENT_JENKINS_VERSION}' } dependencies { implementation 'org:producer:1.0' @@ -99,7 +99,6 @@ class JpiPublishingAndConsumptionTest extends IntegrationSpec { 'commons-lang3-3.9.jar', 'jcip-annotations-1.0.jar', 'findbugs-annotations-1.3.9-1.jar', - 'jsr305-2.0.1.jar', ] as Set resolveConsumer('runtime') == [ @@ -177,6 +176,7 @@ class JpiPublishingAndConsumptionTest extends IntegrationSpec { 'display-url-api-0.2.hpi', 'junit-1.3.hpi', 'script-security-1.13.hpi', + 'jenkins-war-2.401.3.war', ] as Set } @@ -184,7 +184,7 @@ class JpiPublishingAndConsumptionTest extends IntegrationSpec { given: producerBuild << """\ jenkinsPlugin { - jenkinsVersion = '1.580.1' + jenkinsVersion = '${TestSupport.RECENT_JENKINS_VERSION}' } java { registerFeature('credentials') { @@ -203,7 +203,7 @@ class JpiPublishingAndConsumptionTest extends IntegrationSpec { when: consumerBuild << """ jenkinsPlugin { - jenkinsVersion = '1.580.1' + jenkinsVersion = '${TestSupport.RECENT_JENKINS_VERSION}' } dependencies { implementation 'org:producer:1.0' @@ -219,7 +219,9 @@ class JpiPublishingAndConsumptionTest extends IntegrationSpec { resolveConsumer('jenkinsRuntime') == [ 'producer-1.0.hpi', 'ant-1.2.hpi' ] as Set resolveConsumer('jenkinsTestRuntime') == [ 'producer-1.0.hpi', - 'ant-1.2.hpi' ] as Set + 'ant-1.2.hpi', + 'jenkins-war-2.401.3.war', + ] as Set when: consumerBuild << """ @@ -246,7 +248,9 @@ class JpiPublishingAndConsumptionTest extends IntegrationSpec { resolveConsumer('jenkinsTestRuntime') == [ 'producer-1.0.hpi', 'ant-1.2.hpi', - 'credentials-1.9.4.hpi' ] as Set + 'credentials-1.9.4.hpi', + 'jenkins-war-2.401.3.war', + ] as Set manifestEntry('consumer', 'Plugin-Dependencies') == 'producer:1.0,credentials:1.9.4' @@ -270,7 +274,7 @@ class JpiPublishingAndConsumptionTest extends IntegrationSpec { when: consumerBuild << """ jenkinsPlugin { - jenkinsVersion = '1.580.1' + jenkinsVersion = '${TestSupport.RECENT_JENKINS_VERSION}' } dependencies { implementation 'org:producer:1.0' @@ -281,7 +285,7 @@ class JpiPublishingAndConsumptionTest extends IntegrationSpec { resolveConsumer('compile') == JENKINS_CORE_DEPS + [ 'producer-1.0.jar' ] as Set resolveConsumer('runtime') == [ 'producer-1.0.jar' ] as Set resolveConsumer('jenkinsRuntime') == [ 'producer-1.0.hpi' ] as Set - resolveConsumer('jenkinsTestRuntime') == [ 'producer-1.0.hpi' ] as Set + resolveConsumer('jenkinsTestRuntime') == [ 'producer-1.0.hpi', 'jenkins-war-2.401.3.war' ] as Set } private void publishProducer() { @@ -328,122 +332,103 @@ class JpiPublishingAndConsumptionTest extends IntegrationSpec { } private static final JENKINS_CORE_DEPS = [ - 'jenkins-core-1.580.1.jar', - 'annotations-1.0.0.jar', - 'servlet-api-2.4.jar', - 'icon-set-1.0.3.jar', - 'cli-1.580.1.jar', - 'remoting-2.47.jar', - 'version-number-1.1.jar', - 'crypto-util-1.1.jar', - 'jtidy-4aug2000r7-dev-hudson-1.jar', - 'guice-4.0-beta-no_aop.jar', - 'jna-posix-1.0.3.jar', - 'jnr-posix-3.0.1.jar', - 'trilead-putty-extension-1.2.jar', - 'trilead-ssh2-build217-jenkins-5.jar', - 'stapler-groovy-1.231.jar', - 'stapler-jrebel-1.231.jar', - 'windows-package-checker-1.0.jar', - 'stapler-adjunct-zeroclipboard-1.3.5-1.jar', - 'stapler-adjunct-timeline-1.4.jar', - 'stapler-adjunct-codemirror-1.3.jar', - 'bridge-method-annotation-1.13.jar', - 'stapler-jelly-1.231.jar', - 'stapler-1.231.jar', - 'json-lib-2.4-jenkins-2.jar', - 'commons-httpclient-3.1.jar', - 'args4j-2.0.23.jar', - 'bytecode-compatibility-transformer-1.5.jar', - 'access-modifier-annotation-1.4.jar', - 'annotation-indexer-1.7.jar', - 'task-reactor-1.4.jar', - 'localizer-1.10.jar', - 'antlr-2.7.6.jar', - 'xstream-1.4.7-jenkins-1.jar', - 'jfreechart-1.0.9.jar', - 'ant-1.8.3.jar', - 'commons-fileupload-1.3.1-jenkins-1.jar', - 'commons-io-2.4.jar', - 'acegi-security-1.0.7.jar', - 'ezmorph-1.0.6.jar', - 'commons-lang-2.6.jar', - 'commons-digester-2.1.jar', - 'commons-jelly-tags-xml-1.1.jar', - 'commons-jelly-1.1-jenkins-20120928.jar', - 'commons-beanutils-1.8.3.jar', - 'mail-1.4.4.jar', - 'activation-1.1.1-hudson-1.jar', - 'jaxen-1.1-beta-11.jar', + 'access-modifier-annotation-1.31.jar', + 'annotation-indexer-1.17.jar', + 'ant-1.10.13.jar', + 'ant-launcher-1.10.13.jar', + 'antlr4-runtime-4.12.0.jar', + 'args4j-2.33.jar', + 'asm-9.5.jar', + 'asm-analysis-9.5.jar', + 'asm-commons-9.5.jar', + 'asm-tree-9.5.jar', + 'asm-util-9.5.jar', + 'bridge-method-annotation-1.26.jar', + 'checker-qual-3.12.0.jar', + 'cli-2.401.3.jar', + 'commons-beanutils-1.9.4.jar', + 'commons-codec-1.15.jar', + 'commons-collections-3.2.2.jar', + 'commons-compress-1.23.0.jar', + 'commons-discovery-0.5.jar', + 'commons-fileupload-1.5.jar', + 'commons-io-2.11.0.jar', + 'commons-jelly-1.1-jenkins-20230124.jar', + 'commons-jelly-tags-define-1.1-jenkins-20230124.jar', 'commons-jelly-tags-fmt-1.0.jar', - 'commons-jelly-tags-define-1.0.1-hudson-20071021.jar', + 'commons-jelly-tags-xml-1.1.jar', 'commons-jexl-1.1-jenkins-20111212.jar', - 'groovy-all-1.8.9.jar', - 'jline-0.9.94.jar', - 'jansi-1.9.jar', - 'spring-webmvc-2.5.6.SEC03.jar', - 'spring-aop-2.5.6.SEC03.jar', - 'spring-jdbc-1.2.9.jar', - 'spring-context-support-2.5.6.SEC03.jar', - 'spring-web-2.5.6.SEC03.jar', - 'spring-dao-1.2.9.jar', - 'spring-context-2.5.6.SEC03.jar', - 'spring-beans-2.5.6.SEC03.jar', - 'spring-core-2.5.6.SEC03.jar', - 'xpp3-1.1.4c.jar', - 'jstl-1.1.0.jar', - 'commons-discovery-0.4.jar', - 'commons-logging-1.1.3.jar', - 'txw2-20110809.jar', - 'commons-collections-3.2.1.jar', - 'winp-1.22.jar', - 'memory-monitor-1.8.jar', - 'wstx-asl-3.2.9.jar', - 'jmdns-3.4.0-jenkins-3.jar', - 'akuma-1.9.jar', - 'libpam4j-1.6.jar', - 'libzfs-0.5.jar', - 'jna-3.4.0.jar', + 'commons-lang-2.6.jar', + 'commons-logging-1.2.jar', + 'crypto-util-1.8.jar', + 'dom4j-2.1.4.jar', 'embedded_su4j-1.1.jar', - 'sezpoz-1.9.jar', - 'j-interop-2.0.6-kohsuke-1.jar', - 'robust-http-client-1.2.jar', - 'commons-codec-1.8.jar', - 'jbcrypt-0.3m.jar', - 'guava-14.0.jar', - 'jzlib-1.1.3.jar', - 'constant-pool-scanner-1.2.jar', + 'error_prone_annotations-2.18.0.jar', + 'ezmorph-1.0.6.jar', + 'failureaccess-1.0.1.jar', + 'groovy-all-2.4.21.jar', + 'guava-31.1-jre.jar', + 'guice-6.0.0.jar', + 'j-interop-2.0.8-kohsuke-1.jar', + 'j-interopdeps-2.0.8-kohsuke-1.jar', + 'j2objc-annotations-1.3.jar', + 'jakarta.annotation-api-2.1.1.jar', + 'jakarta.inject-api-2.0.1.jar', + 'jakarta.servlet.jsp.jstl-api-1.2.7.jar', + 'jansi-1.11.jar', + 'javax.annotation-api-1.3.2.jar', 'javax.inject-1.jar', - 'aopalliance-1.0.jar', - 'cglib-3.0.jar', - 'jnr-ffi-1.0.7.jar', - 'asm-util-4.0.jar', - 'jnr-constants-0.8.5.jar', - 'asm5-5.0.1.jar', - 'jcommon-1.0.12.jar', - 'ant-launcher-1.8.3.jar', - 'oro-2.0.8.jar', - 'junit-3.8.1.jar', - 'stax-api-1.0-2.jar', + 'javax.servlet-api-3.1.0.jar', + 'jaxen-2.0.0.jar', + 'jbcrypt-1.0.0.jar', + 'jcifs-1.3.18-kohsuke-1.jar', + 'jcip-annotations-1.0.jar', + 'jcl-over-slf4j-2.0.7.jar', + 'jcommon-1.0.23.jar', + 'jenkins-core-2.401.3.jar', + 'jenkins-stapler-support-1.1.jar', + 'jfreechart-1.0.19.jar', + 'jline-2.14.6.jar', + 'jna-5.13.0.jar', + 'json-lib-2.4-jenkins-3.jar', + 'jsr305-3.0.2.jar', + 'jzlib-1.1.3-kohsuke-1.jar', + 'kxml2-2.3.0.jar', + 'listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar', + 'localizer-1.31.jar', + 'log4j-over-slf4j-2.0.7.jar', + 'memory-monitor-1.12.jar', + 'mxparser-1.2.2.jar', + 'producer-1.0.jar', 'relaxngDatatype-20020414.jar', - 'stax-api-1.0.1.jar', - 'j-interopdeps-2.0.6-kohsuke-1.jar', - 'jsr305-2.0.1.jar', - 'asm-commons-4.0.jar', - 'asm-analysis-4.0.jar', - 'asm-tree-4.0.jar', - 'asm-4.0.jar', - 'jffi-1.2.7.jar', - 'jnr-x86asm-1.0.2.jar', - 'dom4j-1.6.1-jenkins-4.jar', - 'javax.annotation-api-1.2.jar', - 'tiger-types-1.3.jar', - 'jdom-1.0.jar', - 'xom-1.0b3.jar', - 'jcifs-1.2.19.jar', - 'xmlParserAPIs-2.6.1.jar', - 'icu4j-2.6.1.jar', - 'xalan-2.6.0.jar', - 'tagsoup-0.9.7.jar', + 'remoting-3107.v665000b_51092.jar', + 'robust-http-client-1.2.jar', + 'sezpoz-1.13.jar', + 'slf4j-api-2.0.7.jar', + 'spotbugs-annotations-4.7.3.jar', + 'spring-aop-5.3.27.jar', + 'spring-beans-5.3.27.jar', + 'spring-context-5.3.27.jar', + 'spring-core-5.3.27.jar', + 'spring-expression-5.3.27.jar', + 'spring-security-core-5.8.2.jar', + 'spring-security-crypto-5.8.2.jar', + 'spring-security-web-5.8.2.jar', + 'spring-web-5.3.27.jar', + 'stapler-1777.v7c6fe6d54a_0c.jar', + 'stapler-adjunct-codemirror-1.3.jar', + 'stapler-adjunct-timeline-1.5.jar', + 'stapler-groovy-1777.v7c6fe6d54a_0c.jar', + 'stapler-jelly-1777.v7c6fe6d54a_0c.jar', + 'symbol-annotation-1.24.jar', + 'task-reactor-1.8.jar', + 'tiger-types-2.2.jar', + 'txw2-20110809.jar', + 'version-number-1.11.jar', + 'websocket-spi-2.401.3.jar', + 'windows-package-checker-1.2.jar', + 'winp-1.30.jar', + 'xpp3-1.1.4c.jar', + 'xstream-1.4.20.jar', ] as Set } diff --git a/src/test/groovy/org/jenkinsci/gradle/plugins/jpi/internal/DependencyLookupSpec.groovy b/src/test/groovy/org/jenkinsci/gradle/plugins/jpi/internal/DependencyLookupSpec.groovy index 577d3759..ee59087e 100644 --- a/src/test/groovy/org/jenkinsci/gradle/plugins/jpi/internal/DependencyLookupSpec.groovy +++ b/src/test/groovy/org/jenkinsci/gradle/plugins/jpi/internal/DependencyLookupSpec.groovy @@ -92,7 +92,7 @@ class DependencyLookupSpec extends Specification { then: actual == ([ - new MavenDependency("org.jenkins-ci.main:jenkins-war:${version}@war"), + new MavenDependency("org.jenkins-ci.main:jenkins-war:${version}"), ] as Set) where: diff --git a/src/test/groovy/org/jenkinsci/gradle/plugins/testing/TestTaskIntegrationSpec.groovy b/src/test/groovy/org/jenkinsci/gradle/plugins/testing/TestTaskIntegrationSpec.groovy index 12b445fd..55d2d120 100644 --- a/src/test/groovy/org/jenkinsci/gradle/plugins/testing/TestTaskIntegrationSpec.groovy +++ b/src/test/groovy/org/jenkinsci/gradle/plugins/testing/TestTaskIntegrationSpec.groovy @@ -55,11 +55,13 @@ class TestTaskIntegrationSpec extends IntegrationSpec { when: def result = gradleRunner() - .withArguments(taskPath, '-s') + .withArguments(taskPath, '-is') .build() then: result.task(taskPath).outcome == TaskOutcome.NO_SOURCE + !result.output.contains('java.lang.ClassNotFoundException') + !result.output.contains('No SLF4J providers were found.') } def 'should work out of the box with JenkinsRule'() { @@ -122,6 +124,8 @@ class TestTaskIntegrationSpec extends IntegrationSpec { then: result.task(taskPath).outcome == TaskOutcome.SUCCESS + !result.output.contains('java.lang.ClassNotFoundException') + !result.output.contains('No SLF4J providers were found.') } def 'should be installed by default'() { @@ -137,6 +141,8 @@ class TestTaskIntegrationSpec extends IntegrationSpec { dependencies { implementation 'org.jenkins-ci.plugins:gradle:1.35' implementation 'org.jenkins-ci.plugins:junit:1.20' + runtimeOnly 'io.jenkins.plugins:javax-mail-api:1.6.2-10' + runtimeOnly 'org.jenkins-ci.plugins:script-security:1172.v35f6a_0b_8207e' } """.stripIndent() def srcTestJava = inProjectDir('src/test/java') @@ -171,10 +177,12 @@ class TestTaskIntegrationSpec extends IntegrationSpec { when: def result = gradleRunner() - .withArguments(taskPath, '-s') + .withArguments(taskPath, '-is') .build() then: result.task(taskPath).outcome == TaskOutcome.SUCCESS + !result.output.contains('java.lang.ClassNotFoundException') + !result.output.contains('No SLF4J providers were found.') } }