diff --git a/tools/gradle-plugin/build.gradle.kts b/tools/gradle-plugin/build.gradle.kts index 4f50923f1..d2a0034bf 100644 --- a/tools/gradle-plugin/build.gradle.kts +++ b/tools/gradle-plugin/build.gradle.kts @@ -15,6 +15,7 @@ plugins { dependencies { compileOnly(gradleApi()) + compileOnly(gradleKotlinDsl()) compileOnly(kotlin("gradle-plugin-api").toString()) { exclude("org.jetbrains.kotlin", "kotlin-stdlib") } @@ -26,6 +27,7 @@ dependencies { api("com.github.jengelman.gradle.plugins:shadow:6.0.0") api(`jetbrains-annotations`) + api("com.jfrog.bintray.gradle:gradle-bintray-plugin:${Versions.bintray}") } version = Versions.console diff --git a/tools/gradle-plugin/src/MiraiConsoleExtension.kt b/tools/gradle-plugin/src/MiraiConsoleExtension.kt index 572a74a76..d0bb3d968 100644 --- a/tools/gradle-plugin/src/MiraiConsoleExtension.kt +++ b/tools/gradle-plugin/src/MiraiConsoleExtension.kt @@ -12,7 +12,10 @@ package net.mamoe.mirai.console.gradle import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import com.jfrog.bintray.gradle.BintrayExtension import org.gradle.api.JavaVersion +import org.gradle.api.XmlProvider +import org.gradle.api.publish.maven.MavenPublication /** * ``` @@ -119,6 +122,165 @@ open class MiraiConsoleExtension { fun excludeDependency(group: String, name: String) { excludedDependencies.add(ExcludedDependency(group, name)) } + + /** + * Bintray 插件成品 JAR 发布 配置. + * + * @see Publishing + * @since 1.1.0 + */ + val publishing: Publishing = Publishing() + + /** + * 控制自动配置 Bintray 发布 + * @since 1.1.0 + */ + var publishingEnabled = true + + /** + * Bintray 插件成品 JAR 发布 配置. + * + * @see [Publishing] + * @since 1.1.0 + */ + inline fun publishing(block: Publishing.() -> Unit) = publishing.run(block) + + /** + * @see publishingEnabled + * @since 1.1.0 + */ + fun disablePublishing() { + publishingEnabled = false + } + + /** + * Bintray 插件成品 JAR 发布 配置. + * + * 对于一个属性 PROP, 会按以下顺序依次尝试读取: + * 1. Gradle 参数 + * - "gradle.properties" + * - ext + * - Gradle -P 启动参数 + * 2. [System.getProperty] "PROP" + * 3. 当前和所有父 project 根目录下 "PROP" 文件的内容 + * 4. [System.getenv] "PROP" + * + * @see publishing + * @since 1.1.0 + */ + class Publishing internal constructor() { + /////////////////////////////////////////////////////////////////////////// + // Required arguments + /////////////////////////////////////////////////////////////////////////// + + /** + * Bintray 账户名. 必须. + * 若为 `null`, 将会以 [Publishing] 中描述的步骤获取 "bintray.user" + * + * @see [Publishing] + */ + var user: String? = null + + /** + * Bintray 账户 key. 必须. + * 若为 `null`, 将会以 [Publishing] 中描述的步骤获取 "bintray.key" + */ + var key: String? = null + + /** + * 目标仓库名称. 必须. + * 若为 `null`, 将会以 [Publishing] 中描述的步骤获取 "bintray.repo" + */ + var repo: String? = null + + /** + * 目标仓库名称. 必须. + * 若为 `null`, 将会以 [Publishing] 中描述的步骤获取 "bintray.package" + */ + var packageName: String? = null + + + /////////////////////////////////////////////////////////////////////////// + // Optional arguments + /////////////////////////////////////////////////////////////////////////// + + // Artifact + + /** + * 发布的 artifact id. 默认为 `project.name`. + * + * artifact id 是类似于 "net.mamoe:mirai-console:1.1.0" 中的 "mirai-console" + */ + var artifactId: String? = null + + /** + * 发布的 group id. 默认为 `project.group`. + * + * group id 是类似于 "net.mamoe:mirai-console:1.1.0" 中的 "net.mamoe" + */ + var groupId: String? = null + + /** + * 发布的版本号, 默认为 `project.version` + * + * 版本号是类似于 "net.mamoe:mirai-console:1.1.0" 中的 "1.1.0" + */ + var version: String? = null + + // Bintray + + /** + * Bintray organization 名. 可选. + * 若为 `null`, 将会以 [Publishing] 中描述的步骤获取 "bintray.org". + * 仍然无法获取时发布到 [user] 账号下的仓库 [repo], 否则发布到指定 [org] 下的仓库 [repo]. + */ + var org: String? = null + + /** + * 上传后自动发布. 默认 `true`. + */ + var publish: Boolean = true + + /** + * 当文件冲突时覆盖. 默认 `false`. + */ + var override: Boolean = false + + // Custom configurations + + internal val bintrayConfigs = mutableListOf Unit>() + internal val bintrayPackageConfigConfigs = mutableListOf Unit>() + internal val mavenPomConfigs = mutableListOf Unit>() + internal val mavenPublicationConfigs = mutableListOf Unit>() + + /** + * 自定义配置 [BintrayExtension],覆盖 + */ + fun bintray(config: BintrayExtension.() -> Unit) { + bintrayConfigs.add(config) + } + + /** + * 自定义配置 [BintrayExtension.PackageConfig] + */ + fun packageConfig(config: BintrayExtension.PackageConfig.() -> Unit) { + bintrayPackageConfigConfigs.add(config) + } + + /** + * 自定义配置 maven pom.xml [XmlProvider] + */ + fun mavenPom(config: XmlProvider.() -> Unit) { + mavenPomConfigs.add(config) + } + + /** + * 自定义配置 [MavenPublication] + */ + fun mavenPublication(config: MavenPublication.() -> Unit) { + mavenPublicationConfigs.add(config) + } + } } enum class MiraiConsoleFrontEndKind { diff --git a/tools/gradle-plugin/src/MiraiConsoleGradlePlugin.kt b/tools/gradle-plugin/src/MiraiConsoleGradlePlugin.kt index 287d4620c..cea8c4286 100644 --- a/tools/gradle-plugin/src/MiraiConsoleGradlePlugin.kt +++ b/tools/gradle-plugin/src/MiraiConsoleGradlePlugin.kt @@ -151,8 +151,9 @@ class MiraiConsoleGradlePlugin : Plugin { afterEvaluate { configureCompileTarget() - registerBuildPluginTasks() kotlinTargets.forEach { configureTarget(it) } + registerBuildPluginTasks() + registerPublishPluginTask() } } } diff --git a/tools/gradle-plugin/src/publishing.kt b/tools/gradle-plugin/src/publishing.kt new file mode 100644 index 000000000..c10f01d8c --- /dev/null +++ b/tools/gradle-plugin/src/publishing.kt @@ -0,0 +1,119 @@ +/* + * Copyright 2020 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/master/LICENSE + */ + +package net.mamoe.mirai.console.gradle + +import org.gradle.api.Project +import org.gradle.api.publish.maven.MavenPublication +import org.gradle.api.tasks.bundling.Jar +import org.gradle.kotlin.dsl.get +import org.gradle.kotlin.dsl.getValue +import org.gradle.kotlin.dsl.provideDelegate +import org.gradle.kotlin.dsl.registering + + +private val Project.selfAndParentProjects: Sequence + get() = generateSequence(this) { it.parent } + +private fun Project.findPropertySmart(propName: String): String? { + return findProperty(propName)?.toString() + ?: System.getProperty(propName) + ?: selfAndParentProjects.map { it.projectDir.resolve(propName) }.find { it.exists() }?.readText() + ?: System.getenv(propName) +} + +private fun Project.findPropertySmartOrFail(propName: String): String { + return findPropertySmart(propName) ?: error("[Mirai Console] Cannot find property for publication: $propName. Please check your 'mirai' configuration.") +} + +internal fun Project.registerPublishPluginTask() { + val mirai = miraiExtension + + bintray { + user = mirai.publishing.user ?: findPropertySmartOrFail("bintray.user") + key = mirai.publishing.key ?: findPropertySmartOrFail("bintray.key") + + setPublications("mavenJava") + setConfigurations("archives") + + publish = mirai.publishing.publish + override = mirai.publishing.override + + pkg.apply { + repo = mirai.publishing.repo ?: findPropertySmartOrFail("bintray.repo") + name = mirai.publishing.packageName ?: findPropertySmartOrFail("bintray.package") + userOrg = mirai.publishing.org ?: findPropertySmart("bintray.org") + + mirai.publishing.bintrayPackageConfigConfigs.forEach { it.invoke(this) } + } + + mirai.publishing.bintrayConfigs.forEach { it.invoke(this) } + } + + @Suppress("DEPRECATION") + val sourcesJar by tasks.registering(Jar::class) { + classifier = "sources" + from(sourceSets["main"].allSource) + } + + publishing { + /* + repositories { + maven { + // change to point to your repo, e.g. http://my.org/repo + url = uri("$buildDir/repo") + } + }*/ + publications.register("mavenJava", MavenPublication::class.java) { publication -> + with(publication) { + from(components["java"]) + + this.groupId = mirai.publishing.groupId ?: project.group.toString() + this.artifactId = mirai.publishing.artifactId ?: project.name + this.version = mirai.publishing.version ?: project.version.toString() + + pom.withXml { xml -> + val root = xml.asNode() + root.appendNode("description", project.description) + root.appendNode("name", project.name) + // root.appendNode("url", vcs) + root.children().last() + + mirai.publishing.mavenPomConfigs.forEach { it.invoke(xml) } + } + + artifact(sourcesJar.get()) + + // TODO: 2020/11/28 -miraip metadata artifact + // TODO: 2020/11/28 -all shadowed artifact + + mirai.publishing.mavenPublicationConfigs.forEach { it.invoke(this) } + } + } + } +} + + +/** + * Configures the [bintray][com.jfrog.bintray.gradle.BintrayExtension] extension. + */ +@PublishedApi +internal fun Project.bintray(configure: com.jfrog.bintray.gradle.BintrayExtension.() -> Unit): Unit = + (this as org.gradle.api.plugins.ExtensionAware).extensions.configure("bintray", configure) + +@PublishedApi +internal val Project.sourceSets: org.gradle.api.tasks.SourceSetContainer + get() = (this as org.gradle.api.plugins.ExtensionAware).extensions.getByName("sourceSets") as org.gradle.api.tasks.SourceSetContainer + +/** + * Configures the [publishing][org.gradle.api.publish.PublishingExtension] extension. + */ +@PublishedApi +internal fun Project.publishing(configure: org.gradle.api.publish.PublishingExtension.() -> Unit): Unit = + (this as org.gradle.api.plugins.ExtensionAware).extensions.configure("publishing", configure)