From 5220da5b5f0a98e4cd454bf0285b0f499644aca2 Mon Sep 17 00:00:00 2001 From: Jan-Philipp Tarnowski Date: Tue, 6 Aug 2024 08:05:44 +0200 Subject: [PATCH] DEVEX-657 Only include licenses of FSM dependencies - License information is now only collected for FSM dependencies - Fixed an issue where 'developmentOnly' dependencies added through the Spring Boot Gradle plugin could be included in the FSM --- build.gradle.kts | 2 +- .../org/gradle/plugins/fsm/FSMPlugin.kt | 46 ++++++++++------ .../gradle/plugins/fsm/FSMPluginExtension.kt | 5 +- .../gradle/plugins/fsm/tasks/bundling/FSM.kt | 22 +------- .../org/gradle/plugins/fsm/FSMManifestTest.kt | 2 +- .../plugins/fsm/FSMPluginExtensionTest.kt | 3 +- .../org/gradle/plugins/fsm/FSMPluginTest.kt | 5 +- .../fsm/descriptor/WebAppComponentsTest.kt | 4 ++ .../fsm/tasks/bundling/FSMLibraryTest.kt | 40 ++++++++++++++ .../fsm/tasks/bundling/FSMLicenseTest.kt | 53 ++++++++++++++++--- .../plugins/fsm/tasks/bundling/FSMTest.kt | 2 - .../fsm-library-dependency.gradle.kts | 17 ++---- .../fsm-quoted-license-entry.gradle.kts | 4 +- .../licenses/fsmdependency.gradle.kts | 17 +++--- .../licenses/fsmnodependency.gradle.kts | 8 +-- .../resources/webapp-project/build.gradle.kts | 21 ++++++++ .../webapp-project/settings.gradle.kts | 3 ++ .../webapp-project/build.gradle.kts | 16 ++++++ .../src/main/fsm-resources/web.xml | 0 .../src/main/java/MyWebApp.java | 29 ++++++++++ 20 files changed, 218 insertions(+), 81 deletions(-) create mode 100644 src/test/kotlin/org/gradle/plugins/fsm/tasks/bundling/FSMLibraryTest.kt create mode 100644 src/test/resources/webapp-project/build.gradle.kts create mode 100644 src/test/resources/webapp-project/settings.gradle.kts create mode 100644 src/test/resources/webapp-project/webapp-project/build.gradle.kts create mode 100644 src/test/resources/webapp-project/webapp-project/src/main/fsm-resources/web.xml create mode 100644 src/test/resources/webapp-project/webapp-project/src/main/java/MyWebApp.java diff --git a/build.gradle.kts b/build.gradle.kts index 9e07ca2..daa83e7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ plugins { id("java-gradle-plugin") id("net.researchgate.release") version "3.0.2" id("org.ajoberstar.grgit") version "5.0.0" - id("com.github.jk1.dependency-license-report") version "2.3" + id("com.github.jk1.dependency-license-report") version "2.9" id("org.cyclonedx.bom") version "1.7.4" } diff --git a/src/main/kotlin/org/gradle/plugins/fsm/FSMPlugin.kt b/src/main/kotlin/org/gradle/plugins/fsm/FSMPlugin.kt index c971489..1304ee4 100644 --- a/src/main/kotlin/org/gradle/plugins/fsm/FSMPlugin.kt +++ b/src/main/kotlin/org/gradle/plugins/fsm/FSMPlugin.kt @@ -12,24 +12,24 @@ import org.gradle.api.artifacts.Dependency import org.gradle.api.plugins.BasePlugin import org.gradle.api.plugins.JavaBasePlugin import org.gradle.api.plugins.JavaPlugin -import org.gradle.api.plugins.JavaPluginExtension -import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.TaskProvider import org.gradle.jvm.tasks.Jar import org.gradle.language.base.plugins.LifecycleBasePlugin import org.gradle.plugins.fsm.annotations.FSMAnnotationsPlugin import org.gradle.plugins.fsm.configurations.FSMConfigurationsPlugin +import org.gradle.plugins.fsm.configurations.FSMConfigurationsPlugin.Companion.FS_CONFIGURATIONS import org.gradle.plugins.fsm.tasks.bundling.FSM import org.gradle.plugins.fsm.tasks.verification.IsolationCheck import org.gradle.plugins.fsm.tasks.verification.ValidateDescriptor import java.util.* -class FSMPlugin: Plugin { +class FSMPlugin : Plugin { override fun apply(project: Project) { project.plugins.apply(JavaPlugin::class.java) project.plugins.apply(FSMConfigurationsPlugin::class.java) project.plugins.apply(FSMAnnotationsPlugin::class.java) + registerWebappsConfiguration(project) project.extensions.create(FSM_EXTENSION_NAME, FSMPluginExtension::class.java, project) @@ -49,6 +49,13 @@ class FSMPlugin: Plugin { configureManifest(project) } + private fun registerWebappsConfiguration(project: Project) { + val webAppsConfiguration = project.configurations.create(WEBAPPS_CONFIGURATION_NAME) + webAppsConfiguration.description = "Combined Runtime Classpath of all Web-Apps registered with the 'webAppComponent' method." + val implementation = project.configurations.getByName(JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME) + implementation.extendsFrom(webAppsConfiguration) + } + private fun configureConfigurationTask(project: Project): Task { val configurationTask = project.tasks.create(CONFIGURE_FSM_TASK_NAME) configurationTask.dependsOn(project.tasks.getByName(GENERATE_LICENSE_REPORT_TASK_NAME)) @@ -77,10 +84,6 @@ class FSMPlugin: Plugin { removeDefaultJarArtifactFromArchives(project) - val javaPlugin = project.extensions.getByType(JavaPluginExtension::class.java) - val runtimeClasspath = javaPlugin.sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).runtimeClasspath - - fsmTask.dependsOn(runtimeClasspath) fsmTask.dependsOn(project.tasks.getByName(GENERATE_LICENSE_REPORT_TASK_NAME)) fsmTask.dependsOn(JavaPlugin.JAR_TASK_NAME) fsmTask.dependsOn(configurationTask) @@ -89,9 +92,6 @@ class FSMPlugin: Plugin { // Validate FSM immediately fsmTask.finalizedBy(validateTask) - val outputs = project.tasks.getByName(JavaPlugin.JAR_TASK_NAME).outputs.files - fsmTask.addToClasspath(runtimeClasspath + outputs) - return fsmTask } @@ -126,16 +126,22 @@ class FSMPlugin: Plugin { jarTask.exclude("module-isolated.xml") } + /** + * Configures the generation of the FSM license report. A CSV license file is added into the module's META-INF/ + * directory. Additionally, we attempt to include all license texts into a subfolder. + * All licenses of third-party libs included in the FSM should be included, i.e., + * + * - Libraries added with `fsModuleCompile`, `fsServerCompile` or `fsWebCompile` + * - Libraries included from web apps added with the `webAppComponent` method in the `firstSpiritModule` block + * - Libraries included with the `libraries` method in the `firstSpiritModule` block + */ private fun configureLicenseReport(project: Project) { val licenseReportTask = project.tasks.withType(ReportTask::class.java).first() + // Library names and web apps are only available after the configuration phase val preparationAction = { _: Task -> - val fsmPluginExtension = project.extensions.getByType(FSMPluginExtension::class.java) - val configurationNames = mutableListOf(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME) - // Library names are only available after the configuration phase - configurationNames.addAll(fsmPluginExtension.libraries.asSequence().mapNotNull { it.configuration?.name }) with(project.extensions.getByType(LicenseReportExtension::class.java)) { - configurations = configurationNames.toTypedArray() + configurations = getLicenseReportConfigurations(project).toTypedArray() } } licenseReportTask.doFirst(preparationAction) @@ -151,11 +157,18 @@ class FSMPlugin: Plugin { with(project.extensions.getByType(LicenseReportExtension::class.java)) { // Set output directory for the report data. outputDir = project.layout.buildDirectory.dir(FSM.LICENSES_DIR_NAME).get().asFile.absolutePath - configurations = arrayOf(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME) + configurations = arrayOf(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME) // Replaced with the correct configurations later, see preparationAction above renderers = arrayOf(CsvReportRenderer()) } } + private fun getLicenseReportConfigurations(project: Project): Set { + val fsmPluginExtension = project.extensions.getByType(FSMPluginExtension::class.java) + return FS_CONFIGURATIONS + // fsModuleCompile, fsServerCompile, fsWebCompile + fsmPluginExtension.libraries.asSequence().mapNotNull { it.configuration?.name } + // library components + WEBAPPS_CONFIGURATION_NAME // webapps declared with the 'webAppComponent' method + } + private fun configureManifest(project: Project) { // Configure each JAR's manifest in the project. This also includes the .fsm file // We cannot configure the tasks directly, because the project is not evaluated yet @@ -205,6 +218,7 @@ class FSMPlugin: Plugin { const val VALIDATE_DESCRIPTOR_TASK_NAME = "validateDescriptor" const val ISOLATION_CHECK_TASK_NAME = "checkIsolation" const val GENERATE_LICENSE_REPORT_TASK_NAME = "generateLicenseReport" + const val WEBAPPS_CONFIGURATION_NAME = "fsmWebappsRuntime" const val VERSIONS_PROPERTIES_FILE = "/fsm-gradle-plugin/versions.properties" } diff --git a/src/main/kotlin/org/gradle/plugins/fsm/FSMPluginExtension.kt b/src/main/kotlin/org/gradle/plugins/fsm/FSMPluginExtension.kt index 98750e9..3855248 100644 --- a/src/main/kotlin/org/gradle/plugins/fsm/FSMPluginExtension.kt +++ b/src/main/kotlin/org/gradle/plugins/fsm/FSMPluginExtension.kt @@ -4,7 +4,6 @@ import de.espirit.mavenplugins.fsmchecker.ComplianceLevel import org.gradle.api.Action import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Project -import org.gradle.api.plugins.JavaPlugin open class FSMPluginExtension(val project: Project) { @@ -21,12 +20,14 @@ open class FSMPluginExtension(val project: Project) { fun webAppComponent(webAppName: String, webAppProject: Project) { fsmWebApps[webAppName] = webAppProject + // Register webapp dependency in extra configuration + val webAppsConfiguration = project.configurations.getByName(FSMPlugin.WEBAPPS_CONFIGURATION_NAME) // This is the same as // implementation project("projectName", configuration: "default") // and is required because of an error with the variant selection regarding the license report plugin. // For more information, see https://github.com/jk1/Gradle-License-Report/issues/170 val projectDependency = project.dependencies.project(mapOf("path" to webAppProject.path, "configuration" to "default")) - project.dependencies.add(JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME, projectDependency) + project.dependencies.add(webAppsConfiguration.name, projectDependency) } /** diff --git a/src/main/kotlin/org/gradle/plugins/fsm/tasks/bundling/FSM.kt b/src/main/kotlin/org/gradle/plugins/fsm/tasks/bundling/FSM.kt index 2da4f24..4bb3455 100644 --- a/src/main/kotlin/org/gradle/plugins/fsm/tasks/bundling/FSM.kt +++ b/src/main/kotlin/org/gradle/plugins/fsm/tasks/bundling/FSM.kt @@ -2,12 +2,11 @@ package org.gradle.plugins.fsm.tasks.bundling import org.gradle.api.Project import org.gradle.api.file.DuplicatesStrategy -import org.gradle.api.file.FileCollection import org.gradle.api.plugins.JavaPlugin -import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction import org.gradle.jvm.tasks.Jar +import org.gradle.plugins.fsm.FSMPlugin import org.gradle.plugins.fsm.FSMPluginExtension import org.gradle.plugins.fsm.compileDependencies import org.gradle.plugins.fsm.configurations.FSMConfigurationsPlugin @@ -40,12 +39,6 @@ abstract class FSM: Jar() { @Internal("Visible for tests") val duplicateFsmResourceFiles = mutableSetOf() - /** - * The fsm runtime classpath. All libraries in this classpath will be copied to 'fsm/lib' folder - */ - @get:InputFiles - var classpath: FileCollection = project.files() - init { archiveExtension.set(FSM_EXTENSION) destinationDirectory.set(project.layout.buildDirectory.dir("fsm")) @@ -59,9 +52,7 @@ abstract class FSM: Jar() { project.moduleScopeDependencies().forEach { lib.from(it.file) } project.configurations.getByName(FS_WEB_COMPILE_CONFIGURATION_NAME).resolve().forEach { lib.from(it) } lib.from(project.tasks.named(JavaPlugin.JAR_TASK_NAME)) - pluginExtension.getWebApps().values - .map { project -> project.configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME) } - .forEach { lib.from(it) } + project.configurations.getByName(FSMPlugin.WEBAPPS_CONFIGURATION_NAME).resolve().forEach { lib.from(it) } pluginExtension.getWebApps().values .map { project -> project.tasks.named(JavaPlugin.JAR_TASK_NAME) } .filter { task -> task.isPresent } @@ -228,15 +219,6 @@ abstract class FSM: Jar() { } - /** - * Adds files to the classpath to include in the FSM archive. - * - * @param classpathToAdd The files to add. - */ - fun addToClasspath(classpathToAdd: FileCollection) { - classpath += classpathToAdd - } - /** * Helper method for executing Unit tests */ diff --git a/src/test/kotlin/org/gradle/plugins/fsm/FSMManifestTest.kt b/src/test/kotlin/org/gradle/plugins/fsm/FSMManifestTest.kt index eb28b97..d5c14e0 100644 --- a/src/test/kotlin/org/gradle/plugins/fsm/FSMManifestTest.kt +++ b/src/test/kotlin/org/gradle/plugins/fsm/FSMManifestTest.kt @@ -28,7 +28,7 @@ class FSMManifestTest { fun manifest() { // Copy test project files from resources folder to temp dir val resourcesUrl = FSMManifestTest::class.java.classLoader.getResource("manifest") - ?: error("manifest not found") + ?: error("test project files not found") val resourcesPath = Paths.get(resourcesUrl.toURI()) resourcesPath.toFile().copyRecursively(testDir) diff --git a/src/test/kotlin/org/gradle/plugins/fsm/FSMPluginExtensionTest.kt b/src/test/kotlin/org/gradle/plugins/fsm/FSMPluginExtensionTest.kt index 464f142..856588e 100644 --- a/src/test/kotlin/org/gradle/plugins/fsm/FSMPluginExtensionTest.kt +++ b/src/test/kotlin/org/gradle/plugins/fsm/FSMPluginExtensionTest.kt @@ -3,7 +3,6 @@ package org.gradle.plugins.fsm import org.assertj.core.api.Assertions.assertThat import org.gradle.api.Project import org.gradle.api.artifacts.ProjectDependency -import org.gradle.api.plugins.JavaPlugin import org.gradle.testfixtures.ProjectBuilder import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -30,7 +29,7 @@ class FSMPluginExtensionTest { assertThat(testling.getWebApps()).containsEntry("web_b", webAppSubprojectB) // Ensure the project has a compile dependency on the subprojects - val dependencyProjects = project.configurations.getByName(JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME) + val dependencyProjects = project.configurations.getByName(FSMPlugin.WEBAPPS_CONFIGURATION_NAME) .dependencies.filterIsInstance().map { it.dependencyProject } assertThat(dependencyProjects).containsExactly(webAppSubprojectA, webAppSubprojectB) } diff --git a/src/test/kotlin/org/gradle/plugins/fsm/FSMPluginTest.kt b/src/test/kotlin/org/gradle/plugins/fsm/FSMPluginTest.kt index 7325fac..e19e18a 100644 --- a/src/test/kotlin/org/gradle/plugins/fsm/FSMPluginTest.kt +++ b/src/test/kotlin/org/gradle/plugins/fsm/FSMPluginTest.kt @@ -50,12 +50,11 @@ class FSMPluginTest { } @Test - fun `FSM-task depends on jar and classes tasks`() { + fun `FSM-task depends on jar task`() { project.plugins.apply(FSMPlugin.NAME) val fsm = project.tasks.getByName(FSMPlugin.FSM_TASK_NAME) - assertThat(fsm).dependsOn(JavaPlugin.JAR_TASK_NAME, JavaPlugin.CLASSES_TASK_NAME, - FSMPlugin.GENERATE_LICENSE_REPORT_TASK_NAME, FSMPlugin.CONFIGURE_FSM_TASK_NAME) + assertThat(fsm).dependsOn(JavaPlugin.JAR_TASK_NAME, FSMPlugin.GENERATE_LICENSE_REPORT_TASK_NAME, FSMPlugin.CONFIGURE_FSM_TASK_NAME) } @Test diff --git a/src/test/kotlin/org/gradle/plugins/fsm/descriptor/WebAppComponentsTest.kt b/src/test/kotlin/org/gradle/plugins/fsm/descriptor/WebAppComponentsTest.kt index e3e0235..3719601 100644 --- a/src/test/kotlin/org/gradle/plugins/fsm/descriptor/WebAppComponentsTest.kt +++ b/src/test/kotlin/org/gradle/plugins/fsm/descriptor/WebAppComponentsTest.kt @@ -5,6 +5,8 @@ import org.assertj.core.api.Assertions.assertThatExceptionOfType import org.gradle.api.GradleException import org.gradle.api.Project import org.gradle.api.plugins.ExtraPropertiesExtension +import org.gradle.api.plugins.JavaPlugin +import org.gradle.plugins.fsm.FSMPlugin.Companion.WEBAPPS_CONFIGURATION_NAME import org.gradle.plugins.fsm.FSMPluginExtension import org.gradle.plugins.fsm.annotations.FSMAnnotationsPlugin import org.gradle.plugins.fsm.configurations.FSMConfigurationsPlugin @@ -25,6 +27,8 @@ class WebAppComponentsTest { project.plugins.apply(FSMAnnotationsPlugin::class.java) project.plugins.apply(FSMConfigurationsPlugin::class.java) project.extensions.create("fsmPlugin", FSMPluginExtension::class.java) + val webAppConfiguration = project.configurations.create(WEBAPPS_CONFIGURATION_NAME) + project.configurations.getByName(JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME).extendsFrom(webAppConfiguration) project.setArtifactoryCredentialsFromLocalProperties() project.defineArtifactoryForProject() diff --git a/src/test/kotlin/org/gradle/plugins/fsm/tasks/bundling/FSMLibraryTest.kt b/src/test/kotlin/org/gradle/plugins/fsm/tasks/bundling/FSMLibraryTest.kt new file mode 100644 index 0000000..c73d7a9 --- /dev/null +++ b/src/test/kotlin/org/gradle/plugins/fsm/tasks/bundling/FSMLibraryTest.kt @@ -0,0 +1,40 @@ +package org.gradle.plugins.fsm.tasks.bundling + +import org.assertj.core.api.Assertions.assertThat +import org.gradle.plugins.fsm.FSMPlugin +import org.gradle.testkit.runner.GradleRunner +import org.gradle.testkit.runner.TaskOutcome +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.io.TempDir +import java.io.File +import java.nio.file.Paths +import java.util.zip.ZipFile + +class FSMLibraryTest { + + @Test + fun `webApp libs`(@TempDir testDir: File) { + val resourcesUrl = FSMLibraryTest::class.java.classLoader.getResource("webapp-project") + ?: error("test project files not found") + val resourcesPath = Paths.get(resourcesUrl.toURI()) + resourcesPath.toFile().copyRecursively(testDir) + + // Execute the gradle build + val result = GradleRunner.create() + .withProjectDir(testDir) + .withArguments(FSMPlugin.FSM_TASK_NAME) + .withPluginClasspath() + .build() + assertThat(result.task(':' + FSMPlugin.FSM_TASK_NAME)?.outcome).isEqualTo(TaskOutcome.SUCCESS) + + // get result + val fsmFile = testDir.resolve("build/fsm/testproject-webapp-1.0-SNAPSHOT.fsm") + assertThat(fsmFile).exists() + ZipFile(fsmFile).use { zipFile -> + // check contents of lib folder + assertThat(zipFile.getEntry("lib/slf4j-api-2.0.13.jar")).isNotNull + assertThat(zipFile.getEntry("lib/fs-isolated-runtime-5.2.220309.jar")).isNull() + assertThat(zipFile.getEntry("lib/fs-isolated-webrt-5.2.220309.jar")).isNull() + } + } +} \ No newline at end of file diff --git a/src/test/kotlin/org/gradle/plugins/fsm/tasks/bundling/FSMLicenseTest.kt b/src/test/kotlin/org/gradle/plugins/fsm/tasks/bundling/FSMLicenseTest.kt index 45ff6fd..0414b43 100644 --- a/src/test/kotlin/org/gradle/plugins/fsm/tasks/bundling/FSMLicenseTest.kt +++ b/src/test/kotlin/org/gradle/plugins/fsm/tasks/bundling/FSMLicenseTest.kt @@ -10,6 +10,7 @@ import org.junit.jupiter.api.fail import org.junit.jupiter.api.io.TempDir import java.nio.file.Files import java.nio.file.Path +import java.nio.file.Paths import java.util.zip.ZipFile import kotlin.io.path.writeText @@ -30,8 +31,8 @@ class FSMLicenseTest { @Test fun `FSM with no dependencies`() { settingsFile.writeText("""rootProject.name = "testFsmNoLicenses"""") - val buildScript = javaClass.getResourceAsStream("/licenses/fsmnodependency.gradle.kts") ?: - fail("Build script '/licenses/fsmnodependency.gradle.kts' not found!") + val buildScript = javaClass.getResourceAsStream("/licenses/fsmnodependency.gradle.kts") + ?: fail("Build script '/licenses/fsmnodependency.gradle.kts' not found!") buildScript.use { buildFile.writeText(it.reader().readText()) } @@ -61,8 +62,8 @@ class FSMLicenseTest { @Test fun `FSM with licenses`() { settingsFile.writeText("""rootProject.name = "testFsmWithLicenses"""") - val buildScript = javaClass.getResourceAsStream("/licenses/fsmdependency.gradle.kts") ?: - fail("Build script '/licenses/fsmdependency.gradle.kts' not found!") + val buildScript = javaClass.getResourceAsStream("/licenses/fsmdependency.gradle.kts") + ?: fail("Build script '/licenses/fsmdependency.gradle.kts' not found!") buildScript.use { buildFile.writeText(it.reader().readText()) } @@ -100,8 +101,8 @@ class FSMLicenseTest { @Test fun `FSM with licenses in library`() { settingsFile.writeText("""rootProject.name = "testFsmLibWithLicenses"""") - val buildScript = javaClass.getResourceAsStream("/licenses/fsm-library-dependency.gradle.kts") ?: - fail("Build script '/licenses/fsm-library-dependency.gradle.kts' not found!") + val buildScript = javaClass.getResourceAsStream("/licenses/fsm-library-dependency.gradle.kts") + ?: fail("Build script '/licenses/fsm-library-dependency.gradle.kts' not found!") buildScript.use { buildFile.writeText(it.reader().readText()) } @@ -136,8 +137,8 @@ class FSMLicenseTest { @Test fun `FSM with escaped quotes in license`() { settingsFile.writeText("""rootProject.name = "testFsmLibWithQuotesInLicense"""") - val buildScript = javaClass.getResourceAsStream("/licenses/fsm-quoted-license-entry.gradle.kts") ?: - fail("Build script '/licenses/fsm-quoted-license-entry.gradle.kts' not found!") + val buildScript = javaClass.getResourceAsStream("/licenses/fsm-quoted-license-entry.gradle.kts") + ?: fail("Build script '/licenses/fsm-quoted-license-entry.gradle.kts' not found!") buildScript.use { buildFile.writeText(it.reader().readText()) } @@ -163,6 +164,42 @@ class FSMLicenseTest { } } + @Test + fun `webApp licenses`() { + val resourcesUrl = FSMLicenseTest::class.java.classLoader.getResource("webapp-project") + ?: error("test project files not found") + val resourcesPath = Paths.get(resourcesUrl.toURI()) + resourcesPath.toFile().copyRecursively(testDir.toFile(), overwrite = true) + + // Execute the gradle build + val result = GradleRunner.create() + .withProjectDir(testDir.toFile()) + .withArguments(FSMPlugin.FSM_TASK_NAME) + .withPluginClasspath() + .build() + assertThat(result.task(':' + FSMPlugin.FSM_TASK_NAME)?.outcome).isEqualTo(TaskOutcome.SUCCESS) + + // get result + val fsmFile = testDir.resolve("build/fsm/testproject-webapp-1.0-SNAPSHOT.fsm") + assertThat(fsmFile.toFile()).exists() + ZipFile(fsmFile.toFile()).use { zipFile -> + val licenseReport = zipFile.getEntry("META-INF/licenses.csv") + val licenses = zipFile.getInputStream(licenseReport).use { + it.reader().readText() + } + + // should have picked up runtime dependency license from WebApp subproject + assertThat(licenses).contains(""""org.slf4j:slf4j-api:2.0.13","http://www.slf4j.org","MIT License","http://www.opensource.org/licenses/mit-license.php"""") + + // but not compile only dependencies + assertThat(licenses).doesNotContain("fs-isolated-runtime") + assertThat(licenses).doesNotContain("fs-isolated-webrt") + + // check presence of license files + assertThat(zipFile.getEntry("META-INF/licenses/slf4j-api-2.0.13.jar/LICENSE.txt")).isNotNull + } + } + companion object { private const val LICENSE_HEADER = """"artifact","moduleUrl","moduleLicense","moduleLicenseUrl", """ diff --git a/src/test/kotlin/org/gradle/plugins/fsm/tasks/bundling/FSMTest.kt b/src/test/kotlin/org/gradle/plugins/fsm/tasks/bundling/FSMTest.kt index cb5200a..0c4d1f8 100644 --- a/src/test/kotlin/org/gradle/plugins/fsm/tasks/bundling/FSMTest.kt +++ b/src/test/kotlin/org/gradle/plugins/fsm/tasks/bundling/FSMTest.kt @@ -496,7 +496,6 @@ class FSMTest { assertThat(fsm.getEntry("web0.xml")).isNotNull assertThat(fsm.getEntry("web1.xml")).isNotNull } - } @Test @@ -520,7 +519,6 @@ class FSMTest { } } - @Test fun `do not include local jar dependencies`(@TempDir tempDir: Path) { val localServerJar = Files.createFile(tempDir.resolve("server-lib.jar")) diff --git a/src/test/resources/licenses/fsm-library-dependency.gradle.kts b/src/test/resources/licenses/fsm-library-dependency.gradle.kts index 8ada9bf..e42f382 100644 --- a/src/test/resources/licenses/fsm-library-dependency.gradle.kts +++ b/src/test/resources/licenses/fsm-library-dependency.gradle.kts @@ -2,7 +2,7 @@ plugins { id("de.espirit.firstspirit-module") } -group = "de.espirit" +group = "com.crownpeak" version = "1.0-SNAPSHOT" repositories { @@ -17,20 +17,11 @@ repositories { val customLib: Configuration by configurations.creating dependencies { - // Test dependency is irrelevant for licensing - testImplementation("org.junit.jupiter:junit-jupiter:5.9.2") - + // custom library dependency should be included customLib(group = "joda-time", name = "joda-time", version = "2.12.2") - // use one, real, dependency - // it needs: - // - license info - // - some transitive dependencies which also have license info - implementation(group = "com.fasterxml.jackson.core", name = "jackson-databind", version = "2.10.0") - - // - compile classpath dependencies - should not be included in licenseInfo - compileOnly(group = "de.espirit.firstspirit", name = "fs-isolated-runtime", version = "5.2.220309") - compileOnly(group = "joda-time", name = "joda-time", version = "2.9") + // FSM dependency + fsModuleCompile(group = "com.fasterxml.jackson.core", name = "jackson-databind", version = "2.10.0") } firstSpiritModule { diff --git a/src/test/resources/licenses/fsm-quoted-license-entry.gradle.kts b/src/test/resources/licenses/fsm-quoted-license-entry.gradle.kts index a431405..07bd5bb 100644 --- a/src/test/resources/licenses/fsm-quoted-license-entry.gradle.kts +++ b/src/test/resources/licenses/fsm-quoted-license-entry.gradle.kts @@ -2,7 +2,7 @@ plugins { id("de.espirit.firstspirit-module") } -group = "de.espirit" +group = "com.crownpeak" version = "1.0-SNAPSHOT" repositories { @@ -16,5 +16,5 @@ repositories { dependencies { // TableLayout has a licenses.csv entry containing quotes, which must be escaped correctly - api(group = "tablelayout", name = "TableLayout", version = "20050920") + fsModuleCompile(group = "tablelayout", name = "TableLayout", version = "20050920") } diff --git a/src/test/resources/licenses/fsmdependency.gradle.kts b/src/test/resources/licenses/fsmdependency.gradle.kts index 5d9e63a..e9252fa 100644 --- a/src/test/resources/licenses/fsmdependency.gradle.kts +++ b/src/test/resources/licenses/fsmdependency.gradle.kts @@ -2,7 +2,7 @@ plugins { id("de.espirit.firstspirit-module") } -group = "de.espirit" +group = "com.crownpeak" version = "1.0-SNAPSHOT" repositories { @@ -15,16 +15,19 @@ repositories { } dependencies { - // Test dependency is irrelevant for licensing - testImplementation("org.junit.jupiter:junit-jupiter:5.9.2") - - // use one, real, dependency + // FSM dependency // it needs: // - license info // - some transitive dependencies which also have license info - implementation(group = "com.fasterxml.jackson.core", name = "jackson-databind", version = "2.10.0") + fsModuleCompile(group = "com.fasterxml.jackson.core", name = "jackson-databind", version = "2.10.0") + + // - runtime classpath dependencies - not included in FSM, should not appear in license info + implementation(group = "org.slf4j", name = "slf4j-api", version = "2.0.13") - // - compile classpath dependencies - should not be included in licenseInfo + // - compile classpath dependencies - should not be included in license info compileOnly(group = "de.espirit.firstspirit", name = "fs-isolated-runtime", version = "5.2.220309") compileOnly(group = "joda-time", name = "joda-time", version = "2.9") + + // - test dependency - should also appear in FSM or license info + testImplementation("org.junit.jupiter:junit-jupiter:5.9.2") } diff --git a/src/test/resources/licenses/fsmnodependency.gradle.kts b/src/test/resources/licenses/fsmnodependency.gradle.kts index 0c009d3..496a732 100644 --- a/src/test/resources/licenses/fsmnodependency.gradle.kts +++ b/src/test/resources/licenses/fsmnodependency.gradle.kts @@ -2,7 +2,7 @@ plugins { id("de.espirit.firstspirit-module") } -group = "de.espirit" +group = "com.crownpeak" version = "1.0-SNAPSHOT" repositories { @@ -15,10 +15,10 @@ repositories { } dependencies { - // Test dependency is irrelevant for licensing - testImplementation("org.junit.jupiter:junit-jupiter:5.9.2") - // - compile classpath dependencies - should not be included in licenseInfo compileOnly(group = "de.espirit.firstspirit", name = "fs-isolated-runtime", version = "5.2.220309") compileOnly(group = "joda-time", name = "joda-time", version = "2.9") + + // - test dependency - should also appear in FSM or license info + testImplementation("org.junit.jupiter:junit-jupiter:5.9.2") } diff --git a/src/test/resources/webapp-project/build.gradle.kts b/src/test/resources/webapp-project/build.gradle.kts new file mode 100644 index 0000000..98ce328 --- /dev/null +++ b/src/test/resources/webapp-project/build.gradle.kts @@ -0,0 +1,21 @@ +plugins { + id("de.espirit.firstspirit-module") +} + +allprojects { + group = "com.crownpeak" + version = "1.0-SNAPSHOT" + + repositories { + maven(url = "https://artifactory.e-spirit.de/artifactory/repo") { + credentials { + username = "${System.getProperty("artifactory_username")}" + password = "${System.getProperty("artifactory_password")}" + } + } + } +} + +firstSpiritModule { + webAppComponent("MyWebApp", project(":webapp-project")) +} diff --git a/src/test/resources/webapp-project/settings.gradle.kts b/src/test/resources/webapp-project/settings.gradle.kts new file mode 100644 index 0000000..4f6af3e --- /dev/null +++ b/src/test/resources/webapp-project/settings.gradle.kts @@ -0,0 +1,3 @@ +include(":webapp-project") + +rootProject.name = "testproject-webapp" \ No newline at end of file diff --git a/src/test/resources/webapp-project/webapp-project/build.gradle.kts b/src/test/resources/webapp-project/webapp-project/build.gradle.kts new file mode 100644 index 0000000..c9d31fd --- /dev/null +++ b/src/test/resources/webapp-project/webapp-project/build.gradle.kts @@ -0,0 +1,16 @@ +plugins { + `java-library` + id("de.espirit.firstspirit-module-annotations") + id("org.springframework.boot") version "3.2.4" +} + +dependencies { + // Since this is in a webapp project, this should be included in the license report... + implementation(group = "org.slf4j", name = "slf4j-api", version = "2.0.13") + + // ...but not this compileOnly dependency + compileOnly(group = "de.espirit.firstspirit", name = "fs-isolated-runtime", version = "5.2.220309") + + // ...and also not this SpringBoot dependency + developmentOnly(group = "de.espirit.firstspirit", name = "fs-isolated-webrt", version = "5.2.220309") +} diff --git a/src/test/resources/webapp-project/webapp-project/src/main/fsm-resources/web.xml b/src/test/resources/webapp-project/webapp-project/src/main/fsm-resources/web.xml new file mode 100644 index 0000000..e69de29 diff --git a/src/test/resources/webapp-project/webapp-project/src/main/java/MyWebApp.java b/src/test/resources/webapp-project/webapp-project/src/main/java/MyWebApp.java new file mode 100644 index 0000000..8fa6742 --- /dev/null +++ b/src/test/resources/webapp-project/webapp-project/src/main/java/MyWebApp.java @@ -0,0 +1,29 @@ +import com.espirit.moddev.components.annotations.WebAppComponent; +import de.espirit.firstspirit.module.WebApp; +import de.espirit.firstspirit.module.WebEnvironment; +import de.espirit.firstspirit.module.descriptor.WebAppDescriptor; + +@WebAppComponent(name = "MyWebApp", webXml = "web.xml") +public class MyWebApp implements WebApp { + + @Override + public void createWar() { + } + + @Override + public void init(WebAppDescriptor webAppDescriptor, WebEnvironment webEnvironment) { + } + + @Override + public void installed() { + } + + @Override + public void uninstalling() { + + } + + @Override + public void updated(String s) { + } +}