All Downloads are FREE. Search and download functionalities are using the official Maven repository.

main.name.remal.gradle_plugins.plugins.common.RebuildIfDependenciesAreChangedPlugin.kt Maven / Gradle / Ivy

There is a newer version: 1.9.2
Show newest version
package name.remal.gradle_plugins.plugins.common

import name.remal.createParentDirectories
import name.remal.forceDelete
import name.remal.gradle_plugins.dsl.ApplyPluginClasses
import name.remal.gradle_plugins.dsl.BaseReflectiveProjectPlugin
import name.remal.gradle_plugins.dsl.EnvironmentVariable
import name.remal.gradle_plugins.dsl.Plugin
import name.remal.gradle_plugins.dsl.PluginAction
import name.remal.gradle_plugins.dsl.PluginActionsGroup
import name.remal.gradle_plugins.dsl.PluginCondition
import name.remal.gradle_plugins.dsl.extensions.all
import name.remal.gradle_plugins.dsl.extensions.get
import name.remal.gradle_plugins.dsl.extensions.logDebug
import name.remal.gradle_plugins.dsl.extensions.logWarn
import name.remal.gradle_plugins.dsl.extensions.mustRunAfter
import name.remal.gradle_plugins.plugins.vcs.AutoVcsVersionExtension
import name.remal.gradle_plugins.plugins.vcs.AutoVcsVersionPlugin
import name.remal.gradle_plugins.plugins.vcs.BaseCreateTagTask
import name.remal.gradle_plugins.plugins.vcs.CreateDependenciesHashTag
import name.remal.gradle_plugins.plugins.vcs.CreateProjectVersionTag
import name.remal.gradle_plugins.plugins.vcs.VcsOperationsExtension
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.plugins.BasePlugin.ASSEMBLE_TASK_NAME
import org.gradle.api.plugins.ExtensionContainer
import org.gradle.api.plugins.JavaBasePlugin.BUILD_TASK_NAME
import org.gradle.api.plugins.JavaBasePlugin.CHECK_TASK_NAME
import org.gradle.api.plugins.JavaPlugin.TEST_TASK_NAME
import org.gradle.api.publish.maven.tasks.AbstractPublishToMaven
import org.gradle.api.tasks.TaskContainer
import java.io.File
import java.lang.System.getenv

@Deprecated(message = "Use automatic dependency updates software like Renovate, Dependabot, etc...")
@Plugin(
    id = "name.remal.rebuild-if-dependencies-are-changed",
    description = "Creates 'createDependenciesHashTag' and handles 'PUBLISH_ONLY_IF_DEPENDENCIES_ARE_CHANGED' environment variable.",
    tags = ["dependencies"],
    isHidden = true
)
@ApplyPluginClasses(AutoVcsVersionPlugin::class)
@EnvironmentVariable("PUBLISH_ONLY_IF_DEPENDENCIES_ARE_CHANGED", description = "Publish only if dependencies are changed")
class RebuildIfDependenciesAreChangedPlugin : BaseReflectiveProjectPlugin() {

    companion object {
        private val PUBLISH_ONLY_IF_DEPENDENCIES_ARE_CHANGED: Boolean by lazy {
            getenv("PUBLISH_ONLY_IF_DEPENDENCIES_ARE_CHANGED")?.toBoolean() == true
                || System.getProperty("PUBLISH_ONLY_IF_DEPENDENCIES_ARE_CHANGED")?.toBoolean() == true
        }

        private const val flagFilesName = "dependencies-changed"
    }

    @PluginAction
    fun TaskContainer.`Create 'createDependenciesHashTag' task`() {
        create("createDependenciesHashTag", CreateDependenciesHashTag::class.java) { task ->
            task.failIfTagExists = false
            task.failIfTagExistsOnCurrentCommit = false

            task.project.rootProject.allprojects { project ->
                project.tasks.all(CreateProjectVersionTag::class.java) { dependentTask ->
                    dependentTask.dependsOn(task)
                }
            }

            task.mustRunAfter {
                task.project.rootProject.allprojects.asSequence()
                    .map(Project::getTasks)
                    .flatMap {
                        sequenceOf(ASSEMBLE_TASK_NAME, TEST_TASK_NAME, CHECK_TASK_NAME, BUILD_TASK_NAME)
                            .mapNotNull(it::findByName)
                    }
                    .toList()
            }


            fun forEachDependentTask(action: (dependentTask: Task) -> Unit) {
                arrayOf>(
                    CreateProjectVersionTag::class.java,
                    BaseCreateTagTask::class.java,
                    AbstractPublishToMaven::class.java
                ).forEach { dependentTaskClass ->
                    val processedTasks = hashSetOf()
                    task.project.rootProject.allprojects { project ->
                        project.tasks.all(dependentTaskClass) { dependentTask ->
                            if (dependentTask !is CreateDependenciesHashTag) {
                                if (processedTasks.add(dependentTask)) {
                                    action(dependentTask)
                                }
                            }
                        }
                    }
                }
            }

            forEachDependentTask { dependentTask ->
                dependentTask.mustRunAfter(task)
            }

            task.doFirst {
                task.project.tagCreatedFile.also { tagCreatedFile ->
                    task.logDebug("Removing tagCreatedFile: {}", tagCreatedFile)
                    tagCreatedFile.forceDelete()
                }
                task.project.tagNotCreatedFile.also { tagNotCreatedFile ->
                    task.logDebug("Removing tagNotCreatedFile: {}", tagNotCreatedFile)
                    tagNotCreatedFile.forceDelete()
                }
            }
            task.onTagCreated {
                task.project.tagCreatedFile.also { tagCreatedFile ->
                    task.logDebug("Creating tagCreatedFile: {}", tagCreatedFile)
                    tagCreatedFile.createParentDirectories().writeText("true")
                }
            }
            if (PUBLISH_ONLY_IF_DEPENDENCIES_ARE_CHANGED) {
                task.onTagNotCreated {
                    task.project.tagNotCreatedFile.also { tagNotCreatedFile ->
                        task.logDebug("Creating tagNotCreatedFile: {}", tagNotCreatedFile)
                        tagNotCreatedFile.createParentDirectories().writeText("true")
                    }

                    forEachDependentTask { dependentTask ->
                        task.logWarn("Disabling {}", dependentTask)
                        dependentTask.enabled = false
                    }
                }
            }
        }
    }

    @PluginActionsGroup(order = Int.MAX_VALUE)
    inner class `If PUBLISH_ONLY_IF_DEPENDENCIES_ARE_CHANGED environment variable equals to true` {

        @PluginCondition(isHidden = true)
        private fun condition(): Boolean {
            return PUBLISH_ONLY_IF_DEPENDENCIES_ARE_CHANGED
        }

        @PluginAction
        fun Project.`Disable publish tasks if project version tag hasn't been created`(extensions: ExtensionContainer) {
            val autoVcsVersion = extensions[AutoVcsVersionExtension::class.java]
            val vcsOperations = extensions[VcsOperationsExtension::class.java]
            rootProject.allprojects { project ->
                project.tasks.all(AbstractPublishToMaven::class.java) { publishTask ->
                    publishTask.onlyIf {
                        val prefixes: List = autoVcsVersion.versionTagPrefixes.let {
                            if (it.isEmpty()) {
                                listOf("")
                            } else {
                                it.sortedDescending()
                            }
                        }

                        val tagNames = vcsOperations.getAllTagNames()

                        return@onlyIf prefixes.any { prefix ->
                            "$prefix${publishTask.project.version}" in tagNames
                        }
                    }
                }
            }
        }

        @PluginAction(order = Int.MAX_VALUE)
        fun ExtensionContainer.`Increment project version by 1`(project: Project) {
            project.tagCreatedFile.let { tagCreatedFile ->
                if (!tagCreatedFile.isFile) {
                    logger.debug("tagCreatedFile doesn't exist: {}", tagCreatedFile)
                    logger.lifecycle("Incrementing VCS version...")
                    this[AutoVcsVersionExtension::class.java].incrementVersionBy++

                } else {
                    logger.debug("tagCreatedFile exists: {}", tagCreatedFile)
                }
                Unit
            }
        }

    }


    private val Project.tagCreatedFile: File get() = buildDir.resolve("$flagFilesName.tag-created")
    private val Project.tagNotCreatedFile: File get() = buildDir.resolve("$flagFilesName.tag-not-created")

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy