Skip to content

Commit

Permalink
1.3.1: Plugin and dev mode fixes, .env parsing
Browse files Browse the repository at this point in the history
Fixes #5
  • Loading branch information
gdude2002 committed Aug 16, 2024
1 parent 7d68089 commit f7be3e6
Show file tree
Hide file tree
Showing 23 changed files with 308 additions and 61 deletions.
2 changes: 2 additions & 0 deletions .github/release.main.kts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ if (releaseBody.contains("---")) {
}

val webhook = mapOf(
"content" to "<@&1264511165543743559>",

"embeds" to listOf(
mapOf(
"color" to 7506394,
Expand Down
1 change: 1 addition & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/kotlinc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions changes/1.3.0.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Gradle Plugins 1.3.0

This version makes some changes change to the KordEx plugin.
This version makes some changes to the KordEx plugin.

## KordEx Plugin

Expand All @@ -12,4 +12,3 @@ The KordEx plugin is now ready for Kord Extensions 2 and is more resilient to me
- **This will become an error in later versions of the plugin.**
- Resolvers can now handle missing repository metadata gracefully and provide a more explicit error when they can't
resolve a version.
-
17 changes: 17 additions & 0 deletions changes/1.3.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Gradle Plugins 1.3.1

This version makes some changes to the KordEx plugin.

## KordEx Plugin

This release improves support for running bots in development, and provides a more sensible way to resolve the latest Kord version (when `"latest"` is specified).

- Add a new `dev` task, which runs your bot in development mode and can recursively parse `.env` files in your project:
- First, the `.env` file in your project's root directory is parsed.
- Then, if your bot is in a submodule, the KordEx plugin will traverse the directory tree down to it, parsing any `.env` files it finds on the way, overriding previously set variables if it finds any duplicates.
- Example: `/root/.env` -> `/root/folder/.env` -> `/root/folder/current-submodule/.env`
- The plugin adds these variables to your in-development bot's runtime environment variables.
- You can disable this by setting `processDotEnv` in your `bot { }` builder to `false`.
- When you supply `"latest"` for the `kordVersion` property, the plugin will now ignore Kord feature branch snapshots, which should make things more consistent and predictable. You can still supply feature branch snapshots manually if you need to use them.
- The plugin now uses reflection to figure out which version of the Kotlin plugin you've applied, rather than inspecting the buildscript's classpath. This fixes a problem where the classpath is empty in some project configurations.
- When writing KordEx plugins using the `plugin { }` builder, the plugin now disables all `Tar` tasks, as building a`.tar` distribution is nonsensical given Kord Extensions can't load them.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ kotlin.incremental=true
org.gradle.jvmargs=-XX:MaxMetaspaceSize=1024m
org.gradle.parallel=true

projectVersion=1.3.0
projectVersion=1.3.1
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ package dev.kordex.gradle.plugins.kordex

import dev.kordex.gradle.plugins.kordex.base.*
import dev.kordex.gradle.plugins.kordex.bot.KordExBotHelper
import dev.kordex.gradle.plugins.kordex.helpers.KspPluginHelper
import dev.kordex.gradle.plugins.kordex.plugins.KordExPluginHelper
import dev.kordex.gradle.plugins.kordex.resolvers.GradleMetadataResolver
import dev.kordex.gradle.plugins.kordex.resolvers.gradle.GradleMetadata
Expand All @@ -18,19 +19,18 @@ import kotlinx.serialization.json.jsonPrimitive
import org.gradle.api.JavaVersion
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaApplication
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.problems.Problems
import org.gradle.api.problems.Severity
import org.gradle.api.tasks.bundling.Jar
import org.gradle.kotlin.dsl.*
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import javax.inject.Inject

@Suppress("UnstableApiUsage")
class KordExPlugin @Inject constructor(problems: Problems) : Plugin<Project> {
private val kotlinJarRegex = "kotlin-compiler-[a-z]+-(.+)\\.jar".toRegex()
// kotlin-gradle-plugin-2.0.20-Beta1-gradle85.jar
private val kotlinJarRegex = "kotlin-gradle-plugin-(.+)-gradle\\d+\\.jar".toRegex()

val problemReporter = problems.forNamespace("dev.kordex")

Expand Down Expand Up @@ -68,7 +68,7 @@ class KordExPlugin @Inject constructor(problems: Problems) : Plugin<Project> {
KordExPluginHelper.process(target, extension)
}

configureCompilerPlugins(target, extension, versions.kordExGradle)
configurePlugins(target, extension, versions.kordExGradle)

addRepos(target, extension, versions.kordEx)

Expand Down Expand Up @@ -100,7 +100,7 @@ class KordExPlugin @Inject constructor(problems: Problems) : Plugin<Project> {
.version["requires"]
?.let { Version(it) }

"latest" -> latestKordMetadata?.getCurrentVersion()
"latest" -> latestKordMetadata?.getCurrentKordVersion()

else -> extension.kordVersion.map(::Version).orNull
} ?: error("Unable to resolve Kord release metadata. Please report this!")
Expand Down Expand Up @@ -159,14 +159,7 @@ class KordExPlugin @Inject constructor(problems: Problems) : Plugin<Project> {
}

target.afterEvaluate {
target.pluginManager.withPlugin("com.google.devtools.ksp") {
logger.info("KSP plugin detected, adding Kord Extensions annotation processor")

target.addDependency(
arrayOf("ksp"),
"$basePackage:annotation-processor:$kordExVersion"
)
}
KspPluginHelper.apply(target, basePackage, kordExVersion)

target.addDependency(
configurations,
Expand Down Expand Up @@ -234,17 +227,23 @@ class KordExPlugin @Inject constructor(problems: Problems) : Plugin<Project> {
return@doLast
}

val kotlinJarName = target.buildscript.configurations
.getByName("classpath")
val classpathJars = target.plugins.toList()
.map { it::class.java.protectionDomain.codeSource.location }
.map { it.path.split("/").last() }

val kotlinJarName = classpathJars
.firstOrNull {
kotlinJarRegex.matches(it.name)
}?.name
kotlinJarRegex.matches(it)
}

if (kotlinJarName == null) {
logger.warn("WARNING | Kotlin JVM plugin applied, but the JAR couldn't be found. Found JARs:")
logger.warn(
"WARNING | Kotlin JVM plugin applied, but the JAR couldn't be found. " +
"Found ${classpathJars.size} JARs:"
)

target.buildscript.configurations.getByName("classpath").forEach {
logger.warn("-> ${it.name}")
classpathJars.forEach {
logger.warn("-> $it")
}

return@doLast
Expand Down Expand Up @@ -303,7 +302,7 @@ class KordExPlugin @Inject constructor(problems: Problems) : Plugin<Project> {
.finalizedBy(checkTask)
}

private fun configureCompilerPlugins(target: Project, extension: KordExExtension, kordExGradle: GradleMetadata) {
private fun configurePlugins(target: Project, extension: KordExExtension, kordExGradle: GradleMetadata) {
val javaVersion = if (extension.jvmTarget.isPresent) {
extension.jvmTarget.get()
} else {
Expand Down Expand Up @@ -335,19 +334,5 @@ class KordExPlugin @Inject constructor(problems: Problems) : Plugin<Project> {
targetCompatibility = JavaVersion.toVersion(javaVersion.toString())
}
}

if (extension.hasBot && extension.bot.mainClass.isPresent) {
target.tasks.withType<Jar> {
manifest {
attributes(
"Main-Class" to extension.bot.mainClass.get()
)
}
}

target.extensions.configure<JavaApplication> {
mainClass = extension.bot.mainClass
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ val latestKordMetadata = if (kordReleases == null && kordSnapshots == null) {
kordReleases
} else {
maxOf(kordReleases, kordSnapshots) { left, right ->
left.getCurrentVersion().compareTo(right.getCurrentVersion())
left.getCurrentKordVersion().compareTo(right.getCurrentKordVersion())
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ package dev.kordex.gradle.plugins.kordex.bot

import dev.kordex.gradle.plugins.kordex.VersionContainer
import dev.kordex.gradle.plugins.kordex.base.KordExExtension
import dev.kordex.gradle.plugins.kordex.helpers.ApplicationPluginHelper
import org.gradle.api.Project
import org.gradle.api.plugins.ApplicationPlugin
import org.gradle.api.tasks.SourceSetContainer
import java.util.*

object KordExBotHelper {
fun process(target: Project, extension: KordExExtension, versions: VersionContainer) {
target.pluginManager.apply(ApplicationPlugin::class.java)
ApplicationPluginHelper.apply(target, extension)

addGeneratedFiles(target, extension, versions)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import org.gradle.api.provider.Property
class KordExBotSettings(props: PropertyFactory) {
val mainClass: Property<String> = props.single()
val dataCollection: Property<DataCollection> = props.single()
val processDotEnv: Property<Boolean> = props.boolean().convention(true)
val voice: Property<Boolean> = props.boolean().convention(true)

fun dataCollection(level: DataCollection?) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

package dev.kordex.gradle.plugins.kordex.helpers

import dev.kordex.gradle.plugins.kordex.base.KordExExtension
import org.gradle.api.Project
import org.gradle.api.plugins.ApplicationPlugin
import org.gradle.api.plugins.JavaApplication
import org.gradle.api.tasks.JavaExec
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.api.tasks.bundling.Jar
import org.gradle.kotlin.dsl.*
import org.slf4j.LoggerFactory
import java.io.File
import kotlin.jvm.java

object ApplicationPluginHelper {
private val logger = LoggerFactory.getLogger(ApplicationPluginHelper::class.java)

fun apply(target: Project, extension: KordExExtension) {
target.plugins.apply(ApplicationPlugin::class.java)

target.extensions.configure<JavaApplication> {
mainClass = extension.bot.mainClass
}

target.tasks.withType<Jar> {
manifest {
attributes(
"Main-Class" to extension.bot.mainClass.get()
)
}
}

val sourceSets = target.extensions.getByType<SourceSetContainer>()

target.tasks.create<JavaExec>("dev") {
group = "application"
description = "Run the configured Kord Extensions bot in development mode"

environment(processDotEnv(target, extension))

jvmArguments.add("-DdevMode=true")

classpath = sourceSets.named("main").get().runtimeClasspath
mainClass = extension.bot.mainClass
}
}

fun processDotEnv(target: Project, extension: KordExExtension): MutableMap<String, String> {
val variables = mutableMapOf<String, String>()

if (!extension.bot.processDotEnv.get()) {
return variables
}

val files = mutableListOf<File>()

val top = target.rootProject.projectDir.toPath()
var current = target.projectDir.toPath()

while (current.startsWith(top)) {
val file = current.resolve(".env").toFile()

if (file.isFile) {
files.add(file)
}

current = current.parent
}

files.reverse()

files.forEach { file ->
logger.info("Loading variables from: $file")

val lines = file.readLines()

for (line in lines) {
var effectiveLine = line.trimStart()

if (effectiveLine.isBlank() || effectiveLine.startsWith("#")) {
continue
}

if (effectiveLine.contains("#")) {
effectiveLine = effectiveLine.substring(0, effectiveLine.indexOf("#"))
}

if (!effectiveLine.contains('=')) {
logger.warn(
"Invalid line in dotenv file: \"=\" not found\n" +
" -> $file\n" +
" -> $effectiveLine"
)

continue
}

val split = effectiveLine
.split("=", limit = 2)
.map { it.trim() }

if (split.size != 2) {
logger.warn(
"Invalid line in dotenv file: variables must be of the form \"name=value\"\n" +
" -> $file\n" +
" -> $effectiveLine"
)

continue
}

logger.trace("${split[0]} -> ${split[1]}")

variables[split[0]] = split[1]
}
}

return variables
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

package dev.kordex.gradle.plugins.kordex.helpers

import dev.kordex.gradle.plugins.kordex.Version
import dev.kordex.gradle.plugins.kordex.base.addDependency
import org.gradle.api.Project
import org.slf4j.LoggerFactory

object KspPluginHelper {
private val logger = LoggerFactory.getLogger(KspPluginHelper::class.java)

fun apply(target: Project, basePackage: String, version: Version) {
target.pluginManager.withPlugin("com.google.devtools.ksp") {
logger.info("KSP plugin detected, adding Kord Extensions annotation processor")

target.addDependency(
arrayOf("ksp"),
"$basePackage:annotation-processor:$version"
)
}
}
}
Loading

0 comments on commit f7be3e6

Please sign in to comment.