diff options
Diffstat (limited to 'dokka-runners/dokkatoo/modules/dokkatoo-plugin/src/main/kotlin/tasks/LogHtmlPublicationLinkTask.kt')
-rw-r--r-- | dokka-runners/dokkatoo/modules/dokkatoo-plugin/src/main/kotlin/tasks/LogHtmlPublicationLinkTask.kt | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/dokka-runners/dokkatoo/modules/dokkatoo-plugin/src/main/kotlin/tasks/LogHtmlPublicationLinkTask.kt b/dokka-runners/dokkatoo/modules/dokkatoo-plugin/src/main/kotlin/tasks/LogHtmlPublicationLinkTask.kt new file mode 100644 index 00000000..c281ce56 --- /dev/null +++ b/dokka-runners/dokkatoo/modules/dokkatoo-plugin/src/main/kotlin/tasks/LogHtmlPublicationLinkTask.kt @@ -0,0 +1,156 @@ +package org.jetbrains.dokka.dokkatoo.tasks + +import org.jetbrains.dokka.dokkatoo.internal.DokkatooInternalApi +import org.jetbrains.dokka.dokkatoo.internal.appendPath +import org.jetbrains.dokka.dokkatoo.tasks.LogHtmlPublicationLinkTask.Companion.ENABLE_TASK_PROPERTY_NAME +import java.net.URI +import java.net.http.HttpClient +import java.net.http.HttpRequest +import java.net.http.HttpResponse +import java.time.Duration +import javax.inject.Inject +import org.gradle.api.provider.Property +import org.gradle.api.provider.ProviderFactory +import org.gradle.api.provider.ValueSource +import org.gradle.api.provider.ValueSourceParameters +import org.gradle.api.tasks.Console +import org.gradle.api.tasks.TaskAction +import org.gradle.kotlin.dsl.* +import org.gradle.work.DisableCachingByDefault + +/** + * Prints an HTTP link in the console when the HTML publication is generated. + * + * The HTML publication requires a web server, since it loads resources via javascript. + * + * By default, it uses + * [IntelliJ's built-in server](https://www.jetbrains.com/help/idea/php-built-in-web-server.html) + * to host the file. + * + * This task can be disabled using the [ENABLE_TASK_PROPERTY_NAME] project property. + */ +@DisableCachingByDefault(because = "logging-only task") +abstract class LogHtmlPublicationLinkTask +@Inject +@DokkatooInternalApi +constructor( + providers: ProviderFactory +) : DokkatooTask() { + + @get:Console + abstract val serverUri: Property<String> + + /** + * Path to the `index.html` of the publication. Will be appended to [serverUri]. + * + * The IntelliJ built-in server requires a relative path originating from the _parent_ directory + * of the IntelliJ project. + * + * For example, + * + * * given an IntelliJ project path of + * ``` + * /Users/rachel/projects/my-project/ + * ``` + * * and the publication is generated with an index file + * ``` + * /Users/rachel/projects/my-project/docs/build/dokka/html/index.html + * ```` + * * then IntelliJ requires the [indexHtmlPath] is + * ``` + * my-project/docs/build/dokka/html/index.html + * ``` + * * so that (assuming [serverUri] is `http://localhost:63342`) the logged URL is + * ``` + * http://localhost:63342/my-project/docs/build/dokka/html/index.html + * ``` + */ + @get:Console + abstract val indexHtmlPath: Property<String> + + init { + // don't assign a group. This task is a 'finalizer' util task, so it doesn't make sense + // to display this task prominently. + group = "other" + + val serverActive = providers.of(ServerActiveCheck::class) { + parameters.uri.convention(serverUri) + } + super.onlyIf("server URL is reachable") { serverActive.get() } + + val logHtmlPublicationLinkTaskEnabled = providers + .gradleProperty(ENABLE_TASK_PROPERTY_NAME) + .orElse("true") + .map(String::toBoolean) + super.onlyIf("task is enabled via property") { + logHtmlPublicationLinkTaskEnabled.get() + } + } + + @TaskAction + fun exec() { + val serverUri = serverUri.orNull + val filePath = indexHtmlPath.orNull + + if (serverUri != null && !filePath.isNullOrBlank()) { + val link = URI(serverUri).appendPath(filePath).toString() + + logger.lifecycle("Generated Dokka HTML publication: $link") + } + } + + /** + * Check if the server URI that can host the generated Dokka HTML publication is accessible. + * + * Use the [HttpClient] included with Java 11 to avoid bringing in a new dependency for such + * a small util. + * + * The check uses a [ValueSource] source to attempt to be compatible with Configuration Cache, but + * I'm not certain that this is necessary, or if a [ValueSource] is the best way to achieve it. + */ + internal abstract class ServerActiveCheck : ValueSource<Boolean, ServerActiveCheck.Parameters> { + + interface Parameters : ValueSourceParameters { + /** E.g. `http://localhost:63342` */ + val uri: Property<String> + } + + override fun obtain(): Boolean { + try { + val uri = URI.create(parameters.uri.get()) + val client = HttpClient.newHttpClient() + val request = HttpRequest + .newBuilder() + .uri(uri) + .timeout(Duration.ofSeconds(1)) + .GET() + .build() + val response = client.send(request, HttpResponse.BodyHandlers.ofString()) + + // don't care about the status - only if the server is available + return response.statusCode() > 0 + } catch (ex: Exception) { + return false + } + } + } + + companion object { + /** + * Control whether the [LogHtmlPublicationLinkTask] task is enabled. Useful for disabling the + * task locally, or in CI/CD, or for tests. + * + * ```properties + * #$GRADLE_USER_HOME/gradle.properties + * org.jetbrains.dokka.dokkatoo.tasks.logHtmlPublicationLinkEnabled=false + * ``` + * + * or via an environment variable + * + * ```env + * ORG_GRADLE_PROJECT_org.jetbrains.dokka.dokkatoo.tasks.logHtmlPublicationLinkEnabled=false + * ``` + */ + const val ENABLE_TASK_PROPERTY_NAME = "org.jetbrains.dokka.dokkatoo.tasks.logHtmlPublicationLinkEnabled" + } +} |