diff --git a/.github/workflows/build-and-publish.yaml b/.github/workflows/build-and-publish.yaml index a327d2c..3082cb3 100644 --- a/.github/workflows/build-and-publish.yaml +++ b/.github/workflows/build-and-publish.yaml @@ -8,7 +8,7 @@ on: jobs: build-and-publish: name: Java Gradle - uses: bakdata/ci-templates/.github/workflows/java-gradle-plugin.yaml@1.41.0 + uses: bakdata/ci-templates/.github/workflows/java-gradle-plugin.yaml@1.42.0 secrets: sonar-token: ${{ secrets.SONARCLOUD_TOKEN }} sonar-organization: ${{ secrets.SONARCLOUD_ORGANIZATION }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 86fe9aa..2e0e77a 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -16,7 +16,7 @@ on: jobs: java-gradle-release: name: Java Gradle - uses: bakdata/ci-templates/.github/workflows/java-gradle-release.yaml@1.41.0 + uses: bakdata/ci-templates/.github/workflows/java-gradle-release.yaml@1.42.0 with: release-type: "${{ inputs.release-type }}" diff --git a/CHANGELOG.md b/CHANGELOG.md index 8692cca..1a20de7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ - no changes! +- no changes! + ## [1.1.11](https://github.com/bakdata/gradle-plugins/tree/1.1.11) (2024-01-29) [Full Changelog](https://github.com/bakdata/gradle-plugins/compare/1.1.10...1.1.11) diff --git a/README.md b/README.md index d19caac..3f4551f 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,32 @@ bakdata gradle plugins ====================== -A collection of small gradle plugin, mostly focused on deployment. +A collection of small Gradle plugins, mostly focused on deployment. -**Sonar** Some defaults for easy integration of sonar on multi-module projects -**Sonatype** is used for uploading to sonatype repos and ultimately publish to Maven Central +- **Sonar** Some defaults for easy integration of sonar on multi-module projects +- **Sonatype** is used for uploading to sonatype repos and ultimately publish to Maven Central +- **Release** adds configurable push behavior for version bumping +## Development +Snapshot versions of these plugins are published to Sonatype. +You can use them in your project by adding the following snippet to your `build.gradle.kts` + +``` +buildscript { + repositories { + maven { + url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots") + } + } + dependencies { + classpath("com.bakdata.gradle:sonar:0.0.1-SNAPSHOT") + classpath("com.bakdata.gradle:sonatype:0.0.1-SNAPSHOT") + classpath("com.bakdata.gradle:release:0.0.1-SNAPSHOT") + } +} + +apply(plugin = "com.bakdata.sonar") +apply(plugin = "com.bakdata.sonatype") +apply(plugin = "com.bakdata.release") +``` diff --git a/build.gradle.kts b/build.gradle.kts index 42564b1..196f411 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,7 +3,7 @@ plugins { id("net.researchgate.release") version "3.0.2" // eat your own dog food - apply the plugins to this plugin project id("com.bakdata.sonar") version "1.1.17" - id("com.bakdata.sonatype") version "1.2.1" + id("com.bakdata.sonatype") version "1.2.2" id("org.hildan.github.changelog") version "1.13.1" id("org.gradle.kotlin.kotlin-dsl") version "2.1.6" apply false id("com.gradle.plugin-publish") version "1.2.1" apply false @@ -52,42 +52,39 @@ subprojects { targetCompatibility = JavaVersion.VERSION_11 } - dependencies { - "testRuntimeOnly"("org.junit.jupiter:junit-jupiter-engine:5.3.0") - "testImplementation"("org.junit.jupiter:junit-jupiter-api:5.3.0") - "testImplementation"("org.assertj", "assertj-core", "3.11.1") - "testImplementation"("org.junit-pioneer", "junit-pioneer", "0.3.0") + apply(plugin = "java-gradle-plugin") + + // config for gradle plugin portal doesn't support snapshot, so we add config only if release version + if (!version.toString().endsWith("-SNAPSHOT")) { + apply(plugin = "com.gradle.plugin-publish") } -} -// config for gradle plugin portal -// doesn't support snapshot, so we add config only if release version -if (!version.toString().endsWith("-SNAPSHOT")) { - subprojects.forEach { project -> - with(project) { - // com.gradle.plugin-publish depends on java-gradle-plugin, but it screws a bit this project - apply(plugin = "java-gradle-plugin") - apply(plugin = "com.gradle.plugin-publish") - project.afterEvaluate { - // java-gradle-plugin requires this block, but we already added the definitions in META-INF for unit testing... - configure { - plugins { - create("${project.name.capitalize()}Plugin") { - id = "com.bakdata.${project.name}" - implementationClass = "com.bakdata.gradle.${project.name.capitalize()}Plugin" - description = project.description - displayName = "Bakdata $name plugin" - } - } - } - // actual block of plugin portal config, need to be done on each subproject as the plugin does not support multi-module projects yet... - configure { - website = "https://github.com/bakdata/gradle-plugins" - vcsUrl = "https://github.com/bakdata/gradle-plugins" - tags = listOf("bakdata", name) + // description is only ready after evaluation + afterEvaluate { + configure { + plugins { + create("${project.name.capitalize()}Plugin") { + id = "com.bakdata.${project.name}" + implementationClass = "com.bakdata.gradle.${project.name.capitalize()}Plugin" + description = project.description + displayName = "Bakdata $name plugin" } } } + + extensions.findByType(com.gradle.publish.PluginBundleExtension::class)?.apply { + // actual block of plugin portal config, need to be done on each subproject as the plugin does not support multi-module projects yet... + website = "https://github.com/bakdata/gradle-plugins" + vcsUrl = "https://github.com/bakdata/gradle-plugins" + tags = listOf("bakdata", name) + } + } + + dependencies { + "testRuntimeOnly"("org.junit.jupiter:junit-jupiter-engine:5.3.0") + "testImplementation"("org.junit.jupiter:junit-jupiter-api:5.3.0") + "testImplementation"("org.assertj", "assertj-core", "3.11.1") + "testImplementation"("org.junit-pioneer", "junit-pioneer", "0.3.0") } } diff --git a/gradle.properties b/gradle.properties index 3afbffa..77065f0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ -version=1.2.3-SNAPSHOT +version=1.3.1-SNAPSHOT org.gradle.caching=true org.gradle.parallel=true diff --git a/release/build.gradle.kts b/release/build.gradle.kts new file mode 100644 index 0000000..5021820 --- /dev/null +++ b/release/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + kotlin("jvm") + id("org.jetbrains.dokka") version "1.9.10" +} +apply(plugin = "org.gradle.kotlin.kotlin-dsl") + +description = "Configures Gradle Release plugin for usage in CI" + +dependencies { + implementation("net.researchgate", "gradle-release", "3.0.2") + implementation("gradle.plugin.org.hildan.gradle", "gradle-github-changelog", "1.12.1") +} diff --git a/release/src/main/kotlin/com/bakdata/gradle/ReleasePlugin.kt b/release/src/main/kotlin/com/bakdata/gradle/ReleasePlugin.kt new file mode 100644 index 0000000..efaa962 --- /dev/null +++ b/release/src/main/kotlin/com/bakdata/gradle/ReleasePlugin.kt @@ -0,0 +1,81 @@ +/* + * The MIT License + * + * Copyright (c) 2024 bakdata GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.bakdata.gradle + +import net.researchgate.release.ReleaseExtension +import org.gradle.api.GradleException +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.configure +import org.hildan.github.changelog.plugin.GitHubChangelogExtension + +class ReleasePlugin : Plugin { + + companion object { + const val DISABLE_PUSH_TO_REMOTE = "release.disablePushToRemote" + const val REQUIRE_BRANCH = "release.requireBranch" + const val GITHUB_REPOSITORY = "changelog.githubRepository" + const val FUTURE_VERSION_TAG = "changelog.futureVersionTag" + const val SINCE_TAG = "changelog.sinceTag" + } + + override fun apply(rootProject: Project) { + if (rootProject.parent != null) { + throw GradleException("Apply this plugin only to the top-level project.") + } + + with(rootProject) { + apply(plugin = "net.researchgate.release") + + val disablePushToRemote: String? = project.findProperty(DISABLE_PUSH_TO_REMOTE)?.toString() + val branch: String? = project.findProperty(REQUIRE_BRANCH)?.toString() + configure { + git { + if (disablePushToRemote?.toBoolean() == true) { + pushToRemote.set(false) + } + branch?.also { + requireBranch.set(it) + } + } + } + + apply(plugin = "org.hildan.github.changelog") + + configure { + project.findProperty(GITHUB_REPOSITORY)?.toString()?.also { + githubRepository = it + } + project.findProperty(FUTURE_VERSION_TAG)?.toString()?.also { + futureVersionTag = it + } + project.findProperty(SINCE_TAG)?.toString()?.also { + sinceTag = it + } + } + } + } +} diff --git a/release/src/test/kotlin/com/bakdata/gradle/ReleasePluginTest.kt b/release/src/test/kotlin/com/bakdata/gradle/ReleasePluginTest.kt new file mode 100644 index 0000000..9fba2f9 --- /dev/null +++ b/release/src/test/kotlin/com/bakdata/gradle/ReleasePluginTest.kt @@ -0,0 +1,184 @@ +/* + * The MIT License + * + * Copyright (c) 2024 bakdata GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.bakdata.gradle + +import com.bakdata.gradle.ReleasePlugin.Companion.DISABLE_PUSH_TO_REMOTE +import com.bakdata.gradle.ReleasePlugin.Companion.FUTURE_VERSION_TAG +import com.bakdata.gradle.ReleasePlugin.Companion.GITHUB_REPOSITORY +import com.bakdata.gradle.ReleasePlugin.Companion.REQUIRE_BRANCH +import com.bakdata.gradle.ReleasePlugin.Companion.SINCE_TAG +import net.researchgate.release.ReleaseExtension +import net.researchgate.release.ReleasePlugin +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatCode +import org.assertj.core.api.Condition +import org.assertj.core.api.SoftAssertions +import org.gradle.api.Project +import org.gradle.api.internal.project.DefaultProject +import org.gradle.kotlin.dsl.extra +import org.gradle.kotlin.dsl.findByType +import org.gradle.testfixtures.ProjectBuilder +import org.hildan.github.changelog.plugin.GitHubChangelogExtension +import org.hildan.github.changelog.plugin.GitHubChangelogPlugin +import org.junit.jupiter.api.Test + +internal class ReleasePluginTest { + + private fun Project.evaluate() { + (this as DefaultProject).evaluate() + } + + @Test + fun testSingleModuleProject() { + val project = ProjectBuilder.builder().build() + + assertThatCode { + project.pluginManager.apply("com.bakdata.release") + project.evaluate() + }.doesNotThrowAnyException() + + SoftAssertions.assertSoftly { softly -> + softly.assertThat(project.plugins) + .haveExactly(1, Condition({ it is ReleasePlugin }, "Has release plugin")) + .haveExactly(1, Condition({ it is GitHubChangelogPlugin }, "Has changelog plugin")) + softly.assertThat(project.extensions.findByType()?.git) + .satisfies { + softly.assertThat(it?.pushToRemote?.get()).isEqualTo("origin") + softly.assertThat(it?.requireBranch?.get()).isEqualTo("main") + } + softly.assertThat(project.extensions.findByType()) + .satisfies { + softly.assertThat(it?.githubRepository).isNull() + softly.assertThat(it?.futureVersionTag).isNull() + softly.assertThat(it?.sinceTag).isNull() + } + } + } + + @Test + fun testDisablePushToRemote() { + val project = ProjectBuilder.builder().build() + + assertThatCode { + project.extra.set(DISABLE_PUSH_TO_REMOTE, "false") + project.pluginManager.apply("com.bakdata.release") + project.evaluate() + }.doesNotThrowAnyException() + + SoftAssertions.assertSoftly { softly -> + softly.assertThat(project.extensions.findByType()?.git?.pushToRemote?.get()) + .isEqualTo("origin") + } + } + + @Test + fun testEnablePushToRemote() { + val project = ProjectBuilder.builder().build() + + assertThatCode { + project.extra.set(DISABLE_PUSH_TO_REMOTE, "true") + project.pluginManager.apply("com.bakdata.release") + project.evaluate() + }.doesNotThrowAnyException() + + SoftAssertions.assertSoftly { softly -> + softly.assertThat(project.extensions.findByType()?.git?.pushToRemote?.get()) + .isEqualTo(false) + } + } + + @Test + fun testRequireBranch() { + val project = ProjectBuilder.builder().build() + + assertThatCode { + project.extra.set(REQUIRE_BRANCH, "my-branch") + project.pluginManager.apply("com.bakdata.release") + project.evaluate() + }.doesNotThrowAnyException() + + SoftAssertions.assertSoftly { softly -> + softly.assertThat(project.extensions.findByType()?.git?.requireBranch?.get()) + .isEqualTo("my-branch") + } + } + + @Test + fun testRepository() { + val project = ProjectBuilder.builder().build() + + assertThatCode { + project.extra.set(GITHUB_REPOSITORY, "my-repo") + project.pluginManager.apply("com.bakdata.release") + project.evaluate() + }.doesNotThrowAnyException() + + SoftAssertions.assertSoftly { softly -> + softly.assertThat(project.extensions.findByType()?.githubRepository) + .isEqualTo("my-repo") + } + } + + @Test + fun testFutureVersionTag() { + val project = ProjectBuilder.builder().build() + + assertThatCode { + project.extra.set(FUTURE_VERSION_TAG, "my-tag") + project.pluginManager.apply("com.bakdata.release") + project.evaluate() + }.doesNotThrowAnyException() + + SoftAssertions.assertSoftly { softly -> + softly.assertThat(project.extensions.findByType()?.futureVersionTag) + .isEqualTo("my-tag") + } + } + + @Test + fun testSinceTag() { + val project = ProjectBuilder.builder().build() + + assertThatCode { + project.extra.set(SINCE_TAG, "my-tag") + project.pluginManager.apply("com.bakdata.release") + project.evaluate() + }.doesNotThrowAnyException() + + SoftAssertions.assertSoftly { softly -> + softly.assertThat(project.extensions.findByType()?.sinceTag) + .isEqualTo("my-tag") + } + } + + @Test + fun testWrongApplicationInMultiModuleProject() { + val parent = ProjectBuilder.builder().withName("parent").build() + val child1 = ProjectBuilder.builder().withName("child1").withParent(parent).build() + + assertThatCode { child1.pluginManager.apply("com.bakdata.release") } + .satisfies { assertThat(it.cause).hasMessageContaining("top-level project") } + } +} diff --git a/release/src/test/resources/META-INF/gradle-plugins/com.bakdata.release.properties b/release/src/test/resources/META-INF/gradle-plugins/com.bakdata.release.properties new file mode 100644 index 0000000..536c0a2 --- /dev/null +++ b/release/src/test/resources/META-INF/gradle-plugins/com.bakdata.release.properties @@ -0,0 +1 @@ +implementation-class=com.bakdata.gradle.ReleasePlugin diff --git a/settings.gradle b/settings.gradle index 7995469..78d1b80 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,4 +7,4 @@ pluginManagement { rootProject.name = 'gradle-plugins' -include 'sonar', 'sonatype' +include 'sonar', 'sonatype', 'release'