Skip to content

Commit

Permalink
Add root-project convention plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
Virtlink committed Jul 6, 2024
1 parent d40c99e commit 99d0a15
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 2 deletions.
4 changes: 4 additions & 0 deletions convention-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ gradlePlugin {
id = "org.metaborg.convention.maven-publish"
implementationClass = "org.metaborg.convention.MavenPublishConventionPlugin"
}
create("convention.root-project") {
id = "org.metaborg.convention.root-project"
implementationClass = "org.metaborg.convention.RootProjectConventionPlugin"
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.metaborg.convention

import org.gradle.api.provider.Property

/** Configuration for the root project convention. */
interface RootProjectConventionExtension {

/** Suffix for all task names. */
val taskNameSuffix: Property<String>

/** The name of the `assemble` task. */
val assembleTaskName: Property<String>
/** The name of the `build` task. */
val buildTaskName: Property<String>
/** The name of the `clean` task. */
val cleanTaskName: Property<String>
/** The name of the `publish` task. */
val publishTaskName: Property<String>
/** The name of the `publishToMavenLocal` task. */
val publishToMavenLocalTaskName: Property<String>
/** The name of the `check` task. */
val checkTaskName: Property<String>
/** The name of the `test` task. */
val testTaskName: Property<String>
/** The name of the `tasks` task. */
val tasksTaskName: Property<String>

/**
* Sets the convention (default values) for the configuration extension.
*/
fun setConvention() {
taskNameSuffix.convention("")
assembleTaskName.convention(taskNameSuffix.map { "assemble$it"} )
buildTaskName.convention(taskNameSuffix.map { "build$it"} )
cleanTaskName.convention(taskNameSuffix.map { "clean$it"} )
publishTaskName.convention(taskNameSuffix.map { "publish$it"} )
publishToMavenLocalTaskName.convention(taskNameSuffix.map { "publish${it}ToMavenLocal"} )
checkTaskName.convention(taskNameSuffix.map { "check$it"} )
testTaskName.convention(taskNameSuffix.map { "test$it"} )
tasksTaskName.convention("allTasks")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package org.metaborg.convention

import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.create

/**
* Configures a root project of a multi-project build, by adding explicit tasks
* that call tasks in the sub-builds and subprojects.
*
* Normally, when you execute a task such as `test` in a multi-project build, you will execute
* all `:test` tasks in all projects. In contrast, when you specifically execute `:test`
* (prefixed with a colon), you execute the `:test` task only in the root project.
* Now, we would like to create a task in this composite build that executes basically
* the equivalent of `test` in each of the included multi-project builds, which would execute
* `:test` in each of the projects. However, this seems to be impossible to write down. Instead,
* we call the root `:test` task in the included build, and in each included build's multi-project
* root project we'll extend the `test` task to depend on the `:test` tasks of the subprojects.
*/
class RootProjectConventionPlugin: Plugin<Project> {
override fun apply(project: Project): Unit = with(project) {
// Add the configuration extension
val extension = extensions.create<RootProjectConventionExtension>("rootProjectConvention")
extension.setConvention()

afterEvaluate {
// Build tasks
tasks.register(extension.assembleTaskName.get()) {
group = "Build"
description = "Assembles the outputs of the subprojects and included builds."
dependsOn(gradle.includedBuilds.map { it.task(":assemble") })
dependsOn(project.subprojects.mapNotNull { it.tasks.findByName("assemble") })
}
tasks.register(extension.buildTaskName.get()) {
group = "Build"
description = "Assembles and tests the subprojects and included builds."
dependsOn(gradle.includedBuilds.map { it.task(":build") })
dependsOn(project.subprojects.mapNotNull { it.tasks.findByName("build") })
}
tasks.register(extension.cleanTaskName.get()) {
group = "Build"
description = "Cleans the outputs of the subprojects and included builds."
dependsOn(gradle.includedBuilds.map { it.task(":clean") })
dependsOn(project.subprojects.mapNotNull { it.tasks.findByName("clean") })
}

// Publishing tasks
tasks.register(extension.publishTaskName.get()) {
group = "Publishing"
description = "Publishes all subprojects and included builds to a remote Maven repository."
dependsOn(gradle.includedBuilds.map { it.task(":publish") })
dependsOn(project.subprojects.mapNotNull { it.tasks.findByName("publish") })
}
tasks.register(extension.publishToMavenLocalTaskName.get()) {
group = "Publishing"
description = "Publishes all subprojects and included builds to the local Maven repository."
dependsOn(gradle.includedBuilds.map { it.task(":publishToMavenLocal") })
dependsOn(project.subprojects.mapNotNull { it.tasks.findByName("publishToMavenLocal") })
}

// Verification tasks
tasks.register(extension.checkTaskName.get()) {
group = "Verification"
description = "Runs all checks on the subprojects and included builds."
dependsOn(gradle.includedBuilds.map { it.task(":check") })
dependsOn(project.subprojects.mapNotNull { it.tasks.findByName("check") })
}
tasks.register(extension.testTaskName.get()) {
group = "Verification"
description = "Runs all unit tests on the subprojects and included builds."
dependsOn(gradle.includedBuilds.map { it.task(":test") })
dependsOn(project.subprojects.mapNotNull { it.tasks.findByName("test") })
}

// Help tasks
tasks.register(extension.tasksTaskName.get()) {
group = "Help"
description = "Displays all tasks of subprojects and included builds."
dependsOn(gradle.includedBuilds.map { it.task(":tasks") })
dependsOn(project.subprojects.mapNotNull { it.tasks.findByName("tasks") })
}
}
}
}
17 changes: 15 additions & 2 deletions docs/content/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,21 @@ To apply the plugin:

```kotlin title="build.gradle.kts"
plugins {
id("org.metaborg.convention.java") version <version>
id("org.metaborg.convention.java") version "<version>"
`java-library`
}
```

!!! note "Kotlin"
When using Kotlin, it will automatically use the configured JVM toolchain.


## Maven Publish Convention
The Maven Publish convention plugin adds metadata to existing publications, and sets up GitHub Packages and Metaborg Artifacts as target publication repositories. A minimal configuration looks like this:

```kotlin title="build.gradle.kts"
plugins {
id("org.metaborg.convention.maven-publish") version <version>
id("org.metaborg.convention.maven-publish") version "<version>"
}

// Group must be set
Expand All @@ -44,3 +48,12 @@ publishing {
}
```


## Root Project Convention
The Root Project convention plugin adds tasks that invoke the corresponding tasks on the sub-builds and subprojects.

```kotlin title="build.gradle.kts"
plugins {
id("org.metaborg.convention.root-project") version "<version>"
}
```

0 comments on commit 99d0a15

Please sign in to comment.