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

ru.vyarus.gradle.plugin.mkdocs.MkdocsPlugin.groovy Maven / Gradle / Ivy

There is a newer version: 4.0.1
Show newest version
package ru.vyarus.gradle.plugin.mkdocs

import groovy.transform.CompileStatic
import groovy.transform.TypeCheckingMode
import org.ajoberstar.gradle.git.publish.GitPublishPlugin
import org.ajoberstar.gradle.git.publish.tasks.GitPublishReset
import org.ajoberstar.grgit.Branch
import org.ajoberstar.grgit.Configurable
import org.ajoberstar.grgit.Grgit
import org.ajoberstar.grgit.operation.BranchChangeOp
import org.ajoberstar.grgit.operation.OpenOp
import org.eclipse.jgit.errors.RepositoryNotFoundException
import org.gradle.api.Plugin
import org.gradle.api.Project
import ru.vyarus.gradle.plugin.mkdocs.task.MkdocsBuildTask
import ru.vyarus.gradle.plugin.mkdocs.task.MkdocsInitTask
import ru.vyarus.gradle.plugin.mkdocs.task.MkdocsTask
import ru.vyarus.gradle.plugin.python.PythonExtension
import ru.vyarus.gradle.plugin.python.PythonPlugin

/**
 * Mkdocs plugin. Provides tasks:
 * 
    *
  • mkdocsInit - create documentation site *
  • mkdocsBuild - build site *
  • mkdocsServe - start livereload server (for development) *
  • mkdocsPublish - publish generated site to github pages (same repo) *
*

* mkdocksInit not use 'mkdocs new', instead more advanced template used with pre-initialized material theme. *

* mkdocsPublish is a custom task (based on * git-publish plugin). This is because native 'mkdocs publish' only support single documentation version and custom * task will manage multi-version documentation site. *

* Plugin will also apply all required pip modules to use mkdocks with material theme and basic plugins * (see {@link ru.vyarus.gradle.plugin.mkdocs.MkdocsExtension#DEFAULT_MODULES}). * * @author Vyacheslav Rusakov * @since 29.10.2017 */ @CompileStatic class MkdocsPlugin implements Plugin { private static final String DOCUMENTATION_GROUP = 'documentation' private static final String MKDOCS_BUILD_TASK = 'mkdocsBuild' private static final String GIT_PUSH_TASK = 'gitPublishPush' private static final String GIT_RESET_TASK = 'gitPublishReset' @Override void apply(Project project) { MkdocsExtension extension = project.extensions.create('mkdocs', MkdocsExtension, project) project.plugins.apply(PythonPlugin) applyDefaults(project, extension) configureMkdocsTasks(project, extension) configurePublish(project, extension) } private void applyDefaults(Project project, MkdocsExtension extension) { // apply default mkdocs, material and minimal plugins // user will be able to override versions, if required project.extensions.getByType(PythonExtension).modules.addAll(MkdocsExtension.DEFAULT_MODULES) project.afterEvaluate { // set publish repository to the current project by default extension.publish.repoUri = extension.publish.repoUri ?: getProjectRepoUri(project) } } @CompileStatic(TypeCheckingMode.SKIP) private void configureMkdocsTasks(Project project, MkdocsExtension extension) { Closure strictConvention = { extension.strict ? ['-s'] : null } project.tasks.register(MKDOCS_BUILD_TASK, MkdocsBuildTask) { it.with { description = 'Build mkdocs documentation' group = DOCUMENTATION_GROUP conventionMapping.with { it.extraArgs = strictConvention it.outputDir = { project.file("${getBuildOutputDir(extension)}") } it.updateSiteUrl = { extension.updateSiteUrl } } } } project.tasks.register('mkdocsServe', MkdocsTask) { it.with { description = 'Start mkdocs live reload server' group = DOCUMENTATION_GROUP command = 'serve' conventionMapping.extraArgs = strictConvention } } project.tasks.register('mkdocsInit', MkdocsInitTask) { it.with { description = 'Create mkdocs documentation' group = DOCUMENTATION_GROUP } } project.tasks.withType(MkdocsTask).configureEach { task -> task.conventionMapping.with { it.workDir = { extension.sourcesDir } it.extras = { extension.extras } } } // simplify direct task usage project.extensions.extraProperties.set(MkdocsTask.simpleName, MkdocsTask) } @CompileStatic(TypeCheckingMode.SKIP) private void configurePublish(Project project, MkdocsExtension extension) { project.plugins.apply(GitPublishPlugin) project.afterEvaluate { MkdocsExtension.Publish publish = extension.publish String path = extension.resolveDocPath() project.configure(project) { gitPublish { repoUri = publish.repoUri branch = publish.branch // folder to checkout branch, apply changes and commit repoDir = file(publish.repoDir) contents { from("${extension.buildDir}") } // required only when multi-version publishing used if (path) { // keep everything (all other versions) except publishing version preserve { include '**' exclude "${path}/**" } } commitMessage = extension.resolveComment() } } } configurePublishTasks(project, extension) } private void configurePublishTasks(Project project, MkdocsExtension extension) { // mkdocsBuild <- gitPublishReset <- gitPublishCopy <- gitPublishCommit <- gitPublishPush <- mkdocsPublish project.tasks.named(GIT_RESET_TASK).configure { it.with { dependsOn MKDOCS_BUILD_TASK applyGitCredentials((GitPublishReset) it) } } project.tasks.named(GIT_PUSH_TASK).configure { it.with { doLast { // UP_TO_DATE fix fixOrphanBranch(project, extension.publish.repoDir, extension.publish.branch) } } } // create dummy task to simplify usage project.tasks.register('mkdocsPublish') { it.with { group = DOCUMENTATION_GROUP description = 'Publish documentation' dependsOn GIT_PUSH_TASK } } } private String getBuildOutputDir(MkdocsExtension extension) { String path = extension.resolveDocPath() return extension.buildDir + (path ? '/' + path : '') } @SuppressWarnings('UnnecessaryCast') private String getProjectRepoUri(Project project) { try { Grgit repo = Grgit.open({ OpenOp op -> op.dir = project.rootDir } as Configurable) return repo.remote.list().find { it.name == 'origin' }?.url } catch (RepositoryNotFoundException ignored) { // repository not initialized case - do nothing (most likely user is just playing with the plugin) } return null } private void applyGitCredentials(GitPublishReset task) { // allow to configure git auth with global gradle properties (instead of swing popup) // http://ajoberstar.org/grgit/grgit-authentication.html task.doFirst { ['username', 'password', 'ssh.private', 'ssh.passphrase'].each { String key = "org.ajoberstar.grgit.auth.$it" String value = task.project.findProperty(key) if (value) { task.project.logger.lifecycle("Git auth gradle property detected: $key") System.setProperty(key, value) } } } } private void fixOrphanBranch(Project project, String repoDir, String branchName) { //https://github.com/ajoberstar/gradle-git-publish/issues/82 // if remote branch not exists gitPublishReset will create orphan local branch and gitPublishPush // will not set tracking after push! (also gitPublishReset will not set tracking on next execution and so // branch will remain orphan on next run, even though remote branch already exists (and plugin knows it!) // This leads to incorrect UP_TO_DATE behaviour: gitPublishPush will NEVER be SKIPPED (even on consequent // task execution) because it tries to check branch status and fails (as branch does not have tracking) // To workaround this behaviour (not terribly incorrect, ofc) setting branch tracking manually, if required Grgit git = Grgit.open({ OpenOp op -> op.dir = project.file(repoDir) } as Configurable) Branch branch = git.branch.current() // normally, this would be executed just once: after first publication, creating remote brnach; in all // other cases, correct tracking would be set automatically if (branch?.name == branchName && branch?.trackingBranch == null) { // set update branch with remote tracking git.branch.change({ BranchChangeOp op -> op.name = branchName op.startPoint = "origin/${branchName}" op.mode = BranchChangeOp.Mode.TRACK } as Configurable) } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy