Merge pull request #981 from mamoe/maven-central

Maven central publish
This commit is contained in:
Karlatemp 2021-02-10 10:11:45 +08:00 committed by GitHub
commit 8b0694c7e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 629 additions and 253 deletions

View File

@ -1,123 +0,0 @@
# This is a basic workflow to help you get started with Actions
name: Bintray Publish
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
release:
types: [ created ]
push:
tags:
- '*-dev*'
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
publish-mirai:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Checkout submodules
run: git submodule update --init --recursive --remote
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: chmod -R 777 *
run: chmod -R 777 *
- name: Init gradle project
run: ./gradlew clean --scan
- name: Check keys
run: >
./gradlew :mirai-core-utils:ensureBintrayAvailable
:mirai-core-api:ensureBintrayAvailable
:mirai-core:ensureBintrayAvailable
:mirai-console:ensureBintrayAvailable
-Dbintray_user=${{ secrets.BINTRAY_USER }} -Pbintray_user=${{ secrets.BINTRAY_USER }}
-Dbintray_key=${{ secrets.BINTRAY_KEY }} -Pbintray_key=${{ secrets.BINTRAY_KEY }}
- name: fillBuildConstants
run: >
./gradlew
fillBuildConstants --scan
-Dbintray_user=${{ secrets.BINTRAY_USER }} -Pbintray_user=${{ secrets.BINTRAY_USER }}
-Dbintray_key=${{ secrets.BINTRAY_KEY }} -Pbintray_key=${{ secrets.BINTRAY_KEY }}
- name: Assemble
run: ./gradlew assemble --scan
- name: Check
run: ./gradlew check --scan
- name: Gradle :mirai-core-utils:publish
run: >
./gradlew :mirai-core-utils:publish --scan
-Dbintray_user=${{ secrets.BINTRAY_USER }} -Pbintray_user=${{ secrets.BINTRAY_USER }}
-Dbintray_key=${{ secrets.BINTRAY_KEY }} -Pbintray_key=${{ secrets.BINTRAY_KEY }}
- name: Gradle :mirai-core-api:publish
run: >
./gradlew :mirai-core-api:publish --scan
-Dbintray_user=${{ secrets.BINTRAY_USER }} -Pbintray_user=${{ secrets.BINTRAY_USER }}
-Dbintray_key=${{ secrets.BINTRAY_KEY }} -Pbintray_key=${{ secrets.BINTRAY_KEY }}
- name: Gradle :mirai-core:publish
run: >
./gradlew :mirai-core:publish --scan
-Dbintray_user=${{ secrets.BINTRAY_USER }} -Pbintray_user=${{ secrets.BINTRAY_USER }}
-Dbintray_key=${{ secrets.BINTRAY_KEY }} -Pbintray_key=${{ secrets.BINTRAY_KEY }}
- name: Gradle :mirai-core-all:bintrayUpload
run: >
./gradlew :mirai-core-all:bintrayUpload --info
-Dbintray_user=${{ secrets.BINTRAY_USER }} -Pbintray_user=${{ secrets.BINTRAY_USER }}
-Dbintray_key=${{ secrets.BINTRAY_KEY }} -Pbintray_key=${{ secrets.BINTRAY_KEY }}
- name: Gradle :mirai-console:bintrayUpload
run: >
./gradlew
:mirai-console:bintrayUpload --info
-Dbintray_user=${{ secrets.BINTRAY_USER }} -Pbintray_user=${{ secrets.BINTRAY_USER }}
-Dbintray_key=${{ secrets.BINTRAY_KEY }} -Pbintray_key=${{ secrets.BINTRAY_KEY }}
- name: Gradle :mirai-console-terminal:bintrayUpload
run: >
./gradlew
:mirai-console-terminal:bintrayUpload --info
-Dbintray_user=${{ secrets.BINTRAY_USER }} -Pbintray_user=${{ secrets.BINTRAY_USER }}
-Dbintray_key=${{ secrets.BINTRAY_KEY }} -Pbintray_key=${{ secrets.BINTRAY_KEY }}
- name: Gradle :mirai-console-compiler-common:bintrayUpload
run: >
./gradlew
:mirai-console-compiler-common:bintrayUpload --info
-Dbintray_user=${{ secrets.BINTRAY_USER }} -Pbintray_user=${{ secrets.BINTRAY_USER }}
-Dbintray_key=${{ secrets.BINTRAY_KEY }} -Pbintray_key=${{ secrets.BINTRAY_KEY }}
- name: Gradle :mirai-console-compiler-annotations:bintrayUpload
run: >
./gradlew
:mirai-console-compiler-annotations:bintrayUpload --info
-Dbintray_user=${{ secrets.BINTRAY_USER }} -Pbintray_user=${{ secrets.BINTRAY_USER }}
-Dbintray_key=${{ secrets.BINTRAY_KEY }} -Pbintray_key=${{ secrets.BINTRAY_KEY }}
# - name: Gradle :mirai-console-intellij:bintrayUpload
# run: >
# ./gradlew
# :mirai-console-intellij:bintrayUpload --info
# -Dbintray_user=${{ secrets.BINTRAY_USER }} -Pbintray_user=${{ secrets.BINTRAY_USER }}
# -Dbintray_key=${{ secrets.BINTRAY_KEY }} -Pbintray_key=${{ secrets.BINTRAY_KEY }}
- name: Publish Gradle plugin
run: >
./gradlew
:mirai-console-gradle:publishPlugins --scan
-Dgradle.publish.key=${{ secrets.GRADLE_PUBLISH_KEY }} -Pgradle.publish.key=${{ secrets.GRADLE_PUBLISH_KEY }}
-Dgradle.publish.secret=${{ secrets.GRADLE_PUBLISH_SECRET }} -Pgradle.publish.secret=${{ secrets.GRADLE_PUBLISH_SECRET }}

125
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,125 @@
# This is a basic workflow to help you get started with Actions
name: Release Publish
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
release:
types: [ created ]
push:
tags:
- '*-dev*'
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
publish-mirai:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Checkout submodules
run: git submodule update --init --recursive --remote
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: chmod -R 777 *
run: chmod -R 777 *
- name: Keys setup
shell: bash
run: |
mkdir build-gpg-sign
echo "$GPG_PRIVATE" > build-gpg-sign/keys.gpg
echo "$GPG_PUBLIC_" > build-gpg-sign/keys.gpg.pub
mkdir build-secret-keys
echo "$SONATYPE_USER" > build-secret-keys/sonatype.key
echo "$SONATYPE_KEY" >> build-secret-keys/sonatype.key
echo "$BINTRAY_USER" > build-secret-keys/bintray.key
echo "$BINTRAY_KEY" >> build-secret-keys/bintray.key
env:
GPG_PRIVATE: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PUBLIC_: ${{ secrets.GPG_PUBLIC_KEY }}
SONATYPE_USER: ${{ secrets.SONATYPE_USER }}
SONATYPE_KEY: ${{ secrets.SONATYPE_KEY }}
BINTRAY_USER: ${{ secrets.BINTRAY_USER }}
BINTRAY_KEY: ${{ secrets.BINTRAY_KEY }}
- name: Init gradle project
run: ./gradlew clean --scan
- name: Check keys
run: >
./gradlew
:mirai-core-utils:ensureBintrayAvailable
:mirai-core-api:ensureBintrayAvailable
:mirai-core:ensureBintrayAvailable
:mirai-console:ensureBintrayAvailable
:mirai-core-utils:ensureMavenCentralAvailable
:mirai-core-api:ensureMavenCentralAvailable
:mirai-core:ensureMavenCentralAvailable
:mirai-console:ensureMavenCentralAvailable
- name: fillBuildConstants
run: >
./gradlew
fillBuildConstants --scan
- name: Assemble
run: ./gradlew assemble --scan
- name: Check
run: ./gradlew check --scan
- name: Gradle :mirai-core-utils:publish
run: >
./gradlew :mirai-core-utils:publish --scan
- name: Gradle :mirai-core-api:publish
run: >
./gradlew :mirai-core-api:publish --scan
- name: Gradle :mirai-core:publish
run: >
./gradlew :mirai-core:publish --scan
- name: Gradle :mirai-core-all:publish
run: >
./gradlew :mirai-core-all:publish --info
- name: Gradle :mirai-console:publish
run: >
./gradlew
:mirai-console:publish --info
- name: Gradle :mirai-console-terminal:publish
run: >
./gradlew
:mirai-console-terminal:publish --info
- name: Gradle :mirai-console-compiler-common:publish
run: >
./gradlew
:mirai-console-compiler-common:publish --info
- name: Gradle :mirai-console-compiler-annotations:publish
run: >
./gradlew
:mirai-console-compiler-annotations:publish --info
- name: Publish Gradle plugin
run: >
./gradlew
:mirai-console-gradle:publishPlugins --scan
-Dgradle.publish.key=${{ secrets.GRADLE_PUBLISH_KEY }} -Pgradle.publish.key=${{ secrets.GRADLE_PUBLISH_KEY }}
-Dgradle.publish.secret=${{ secrets.GRADLE_PUBLISH_SECRET }} -Pgradle.publish.secret=${{ secrets.GRADLE_PUBLISH_SECRET }}
- name: Gradle :ci-release-helper:closeAndReleaseRepository
run: >
./gradlew
:ci-release-helper:closeAndReleaseRepository --info

7
.gitignore vendored
View File

@ -45,4 +45,9 @@ keys.properties
token.txt
bintray.user.txt
bintray.key.txt
bintray.key.txt
# For gpg sign
/build-gpg-sign
# Name for IDEA direction sorting
build-secret-keys/

View File

@ -64,6 +64,7 @@ configure<kotlinx.validation.ApiValidationExtension> {
}
project.ext.set("isAndroidSDKAvailable", false)
GpgSigner.setup(project)
tasks.register("publishMiraiCoreArtifactsToMavenLocal") {
group = "mirai"
@ -138,9 +139,14 @@ subprojects {
tasks.register("cleanExceptIntellij") {
group = "build"
allprojects.forEach {
if (it.name != "mirai-console-intellij")
dependsOn(it.tasks.findByName("clean"))
allprojects.forEach { proj ->
if (proj.name != "mirai-console-intellij") {
// Type mismatch
// proj.tasks.findByName("clean")?.let(::dependsOn)
proj.tasks.findByName("clean")?.let { dependsOn(it) }
}
}
}

View File

@ -0,0 +1,108 @@
/*
* Copyright 2019-2021 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
*/
import org.gradle.api.Project
import java.io.File
open class GpgSigner(private val workdir: File) {
private val workdirParent by lazy { workdir.parentFile ?: error("Assertion error: No parent file of $workdir") }
private val workdirName by lazy { workdir.name }
fun verbose(msg: String) {
println("[GPG SIGN] [Verbose] $msg")
}
@Suppress("RemoveExplicitTypeArguments")
private val verbosePrintOnce by lazy<Unit> {
verbose("GPG Signer working dir: $workdir")
verbose("GPG command working dir: $workdirParent")
}
constructor(workdir: String) : this(File(workdir))
object NoopSigner : GpgSigner("build/gpg-noop") {
override fun processGpg(vararg cmds: String) {
}
override fun importKey(file: File) {
}
override fun doSign(file: File) {
}
}
companion object {
private var initialized: Boolean = false
var signer: GpgSigner = NoopSigner
fun setup(project: Project) {
if (initialized) return
initialized = true
val rootProject = project.rootProject
val gpg = rootProject.projectDir.resolve("build-gpg-sign")
gpg.mkdirs()
val keyFile = gpg.resolve("keys.gpg")
val keyFilePub = gpg.resolve("keys.gpg.pub")
if (keyFile.isFile) {
val homedir = gpg.resolve("homedir")
signer = GpgSigner(homedir.absolutePath)
if (!homedir.resolve("pubring.kbx").isFile) {
signer.importKey(keyFile)
if (keyFilePub.isFile) {
signer.importKey(keyFilePub)
} else {
println("[GPG SIGN] Missing public key storage")
println("[GPG SIGN] GPG Sign 2nd verity may failed.")
}
}
} else {
println("[GPG SIGN] GPG Key not found.")
println("[GPG SIGN] GPG Signer will not setup")
println("[GPG SIGN] Key file location: $keyFile")
}
}
}
open fun processGpg(
vararg cmds: String
) {
workdir.mkdirs()
verbosePrintOnce
val response = ProcessBuilder().command(ArrayList<String>().apply {
add("gpg")
add("--homedir"); add(workdirName)
addAll(cmds)
}.also {
verbose("Processing " + it.joinToString(" "))
}).directory(workdirParent)
.inheritIO()
.start()
.waitFor()
if (response != 0) {
error("Exit Response $response")
}
}
open fun importKey(file: File) {
processGpg("--batch", "--import", file.toString())
}
open fun doSign(file: File) {
if (!file.isFile) {
println("[GPG SIGN] $file not a file")
return
}
println("[GPG SIGN] Signing $file")
File("${file.path}.asc").delete()
processGpg("-a", "--batch", "--no-tty", "--detach-sig", "--sign", file.toString())
processGpg("--verify", "$file.asc", file.toString())
}
}

View File

@ -13,6 +13,7 @@
)
import com.github.jengelman.gradle.plugins.shadow.ShadowPlugin
import keys.SecretKeys
import org.gradle.api.Project
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.bundling.Jar
@ -21,17 +22,9 @@ import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.register
import org.gradle.kotlin.dsl.registering
/*
* 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
*/
fun Project.configureBintray() {
fun Project.configureRemoteRepos(
bintrayPkgName: String = "mirai-core"
) {
tasks.register("ensureBintrayAvailable") {
doLast {
if (!project.isBintrayAvailable()) {
@ -39,19 +32,53 @@ fun Project.configureBintray() {
}
}
}
tasks.register("ensureMavenCentralAvailable") {
doLast {
if (GpgSigner.signer == GpgSigner.NoopSigner) {
error("GPG Signer isn't available.")
}
val keys = SecretKeys.getCache(project)
if (!keys.loadKey("sonatype").isValid) {
error("Maven Central isn't available.")
}
}
}
if (isBintrayAvailable()) {
publishing {
repositories {
publishing {
// sonatype
val keys = SecretKeys.getCache(project)
repositories {
val sonatype = keys.loadKey("sonatype")
if (sonatype.isValid) {
maven {
setUrl("https://api.bintray.com/maven/him188moe/mirai/mirai-core/;publish=1;override=1")
name = "MavenCentral"
// Maven Central
setUrl("https://oss.sonatype.org/service/local/staging/deploy/maven2")
credentials {
username = sonatype.user
password = sonatype.password
}
}
} else {
println("SonaType is not available")
}
if (isBintrayAvailable()) {
maven {
name = "Bintray"
setUrl("https://api.bintray.com/maven/him188moe/mirai/$bintrayPkgName/;publish=1;override=1")
credentials {
username = Bintray.getUser(project)
password = Bintray.getKey(project)
}
}
} else {
println("bintray isn't available.")
}
}
}
}
@ -63,30 +90,29 @@ inline fun Project.configurePublishing(
bintrayPkgName: String = artifactId,
vcs: String = "https://github.com/mamoe/mirai"
) {
configureBintray()
configureRemoteRepos(
bintrayPkgName = bintrayPkgName
)
apply<ShadowPlugin>()
if (!project.isBintrayAvailable()) {
println("bintray isn't available. NO PUBLICATIONS WILL BE SET")
return
}
if (project.isBintrayAvailable()) {
bintray {
user = Bintray.getUser(project)
key = Bintray.getKey(project)
bintray {
user = Bintray.getUser(project)
key = Bintray.getKey(project)
setPublications("mavenJava")
setConfigurations("archives")
setPublications("mavenJava")
setConfigurations("archives")
publish = true
override = true
publish = true
override = true
pkg.apply {
repo = bintrayRepo
name = bintrayPkgName
setLicenses("AGPLv3")
publicDownloadNumbers = true
vcsUrl = vcs
pkg.apply {
repo = bintrayRepo
name = bintrayPkgName
setLicenses("AGPLv3")
publicDownloadNumbers = true
vcsUrl = vcs
}
}
}
@ -94,6 +120,10 @@ inline fun Project.configurePublishing(
archiveClassifier.set("sources")
from(sourceSets["main"].allSource)
}
val stubJavadoc = tasks.register("javadocJar", Jar::class) {
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
archiveClassifier.set("javadoc")
}
publishing {
publications {
@ -104,16 +134,15 @@ inline fun Project.configurePublishing(
setArtifactId(artifactId)
version = project.version.toString()
pom.withXml {
val root = asNode()
root.appendNode("description", description)
root.appendNode("name", project.name)
root.appendNode("url", vcs)
root.children().last()
}
setupPom(
project = project,
vcs = vcs
)
artifact(sourcesJar.get())
artifact(stubJavadoc.get())
}
}
configGpgSign(this@configurePublishing)
}
}

View File

@ -21,7 +21,7 @@ fun logPublishing(message: String) {
}
fun Project.configureMppPublishing() {
configureBintray()
configureRemoteRepos()
// mirai does some magic on MPP targets
afterEvaluate {
@ -42,10 +42,13 @@ fun Project.configureMppPublishing() {
.forEach { publication ->
val moduleFile = buildDir.resolve("publications/${publication.name}/module.json")
if (moduleFile.exists()) {
publication.artifact(object :
val artifact = (object :
org.gradle.api.publish.maven.internal.artifact.FileBasedMavenArtifact(moduleFile) {
override fun getDefaultExtension() = "module"
})
publication.artifact(artifact)
GpgSigner.signer.doSign(moduleFile)
publication.artifact(GPGSignMavenArtifact(artifact))
}
}
}
@ -61,9 +64,10 @@ fun Project.configureMppPublishing() {
logPublishing("Publications: ${publications.joinToString { it.name }}")
publications.filterIsInstance<MavenPublication>().forEach { publication ->
if (publication.name != "kotlinMultiplatform") {
publication.artifact(stubJavadoc)
}
// Maven Central always require javadoc.jar
publication.artifact(stubJavadoc)
publication.setupPom(project)
logPublishing(publication.name)
when (val type = publication.name) {
@ -86,6 +90,7 @@ fun Project.configureMppPublishing() {
}
}
}
configGpgSign(this@configureMppPublishing)
}
}
}
@ -129,6 +134,6 @@ val publishPlatformArtifactsInRootModule: Project.(MavenPublication) -> Unit = {
}
}
private fun MavenArtifact.smartToString(): String {
public fun MavenArtifact.smartToString(): String {
return "${file.path}, classifier=${classifier}, ext=${extension}"
}

View File

@ -0,0 +1,102 @@
/*
* Copyright 2019-2021 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
*/
import org.gradle.api.Project
import org.gradle.api.internal.tasks.DefaultTaskDependency
import org.gradle.api.internal.tasks.TaskDependencyInternal
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenArtifact
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.maven.internal.artifact.AbstractMavenArtifact
import org.gradle.api.publish.maven.internal.publication.DefaultMavenPublication
import java.io.File
open class GPGSignMavenArtifact(
private val delegate: MavenArtifact,
private val tasks: TaskDependencyInternal = TaskDependencyInternal.EMPTY
) : AbstractMavenArtifact() {
override fun getFile(): File {
return File(delegate.file.path + ".asc")
}
override fun shouldBePublished(): Boolean = (delegate as? AbstractMavenArtifact)?.shouldBePublished() ?: true
override fun getDefaultExtension(): String = delegate.extension + ".asc"
override fun getDefaultClassifier(): String = delegate.classifier ?: ""
override fun getDefaultBuildDependencies(): TaskDependencyInternal = tasks
}
class NameCounter(val name: String) {
var counter = 0
val nextName: String
get() = name + if (counter == 0) {
counter = 1; ""
} else {
counter++; counter
}
}
object PublishingAccess {
fun getMetadataArtifacts(publication: MavenPublication): Collection<MavenArtifact> {
if (publication is DefaultMavenPublication) {
return DefaultMavenPublication::class.java.getDeclaredField("metadataArtifacts")
.also { it.isAccessible = true }
.get(publication) as Collection<MavenArtifact>
}
return emptyList()
}
}
fun PublishingExtension.configGpgSign(project: Project) {
if (GpgSigner.signer === GpgSigner.NoopSigner) {
return
}
val tasks = DefaultTaskDependency()
val signArtifactsGPG = NameCounter("signArtifactsGPG")
publications.forEach { publication ->
if (publication is MavenPublication) {
val artifacts0: Collection<Pair<Collection<MavenArtifact>, (MavenArtifact) -> Unit>> = listOf(
publication.artifacts to { publication.artifact(it) }, // main artifacts
PublishingAccess.getMetadataArtifacts(publication).let { artifacts -> // pom files
if (artifacts is MutableCollection<MavenArtifact>) {
artifacts to { artifacts.add(it) }
} else {
artifacts to { publication.artifact(it) }
}
}
)
val allArtifacts = artifacts0.flatMap { it.first }.toList()
if (allArtifacts.isNotEmpty()) {
tasks.add(project.tasks.create(signArtifactsGPG.nextName) {
group = "publishing"
doLast {
allArtifacts.forEach { artifact ->
if ((artifact as? AbstractMavenArtifact)?.shouldBePublished() != false) {
GpgSigner.signer.doSign(artifact.file)
}
}
}
allArtifacts.forEach {
dependsOn(it.buildDependencies)
}
})
artifacts0.forEach { (artifacts, artifactsRegister) ->
artifacts.toList().forEach { artifact ->
logPublishing("gpg sign for artifact ${artifact.smartToString()}")
artifactsRegister(GPGSignMavenArtifact(artifact, tasks))
}
}
}
}
}
}

View File

@ -15,6 +15,7 @@
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.publish.PublicationContainer
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.TaskContainer
import org.gradle.kotlin.dsl.ExistingDomainObjectDelegate
import org.gradle.kotlin.dsl.RegisteringDomainObjectDelegateProviderWithTypeAndAction
@ -77,3 +78,40 @@ val Project.publications: PublicationContainer
}
return ret
}
fun MavenPublication.setupPom(
project: Project,
vcs: String = "https://github.com/mamoe/mirai"
) {
pom {
scm {
url.set(vcs)
connection.set("scm:$vcs.git")
developerConnection.set("scm:${vcs.replace("https:", "git:")}.git")
}
licenses {
license {
name.set("GNU AGPLv3")
url.set("https://github.com/mamoe/mirai/blob/master/LICENSE")
}
}
developers {
developer {
id.set("mamoe")
name.set("Mamoe Technologies")
email.set("support@mamoe.net")
}
}
}
pom.withXml {
val root = asNode()
root.appendNode("description", project.description)
root.appendNode("name", project.name)
root.appendNode("url", vcs)
}
}

View File

@ -12,7 +12,7 @@
import org.gradle.api.attributes.Attribute
object Versions {
const val project = "2.4-M1"
const val project = "2.4-M1-dev-publish-3"
const val core = project
const val console = project

View File

@ -0,0 +1,123 @@
/*
* Copyright 2019-2021 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 keys
import org.gradle.api.Project
import java.io.BufferedReader
open class SecretKeys(
val type: String,
val user: String,
val password: String
) {
class Invalid(
type: String,
override val isDisabled: Boolean = false
) : SecretKeys(type, "", "") {
override val isValid: Boolean get() = false
override fun requireNotInvalid(): Nothing {
error(
"""
Key $type not found.
Please lease specify by creating a file $type.key in projectDir/build-secret-keys
or by providing JVM parameter '$type.user', `$type.password`
""".trimIndent()
)
}
}
companion object {
val keyCaches = mutableMapOf<Project, ProjectKeysCache>()
@JvmStatic
fun getCache(project: Project): ProjectKeysCache =
keyCaches.computeIfAbsent(project, SecretKeys::ProjectKeysCache)
}
class ProjectKeysCache(val project: Project) {
val keys = mutableMapOf<String, SecretKeys>()
fun loadKey(type: String) = keys.computeIfAbsent(type, this::loadKey0)
private fun loadKey0(type: String): SecretKeys {
project.parent?.let { parent ->
getCache(parent).loadKey(type).takeIf {
it.isValid || it.isDisabled
}?.let { return it }
}
val secretKeys = project.projectDir.resolve("build-secret-keys")
kotlin.run {
val secretKeyFile = secretKeys.resolve("$type.disable").takeIf { it.isFile }
?: secretKeys.resolve("$type.disable.txt")
if (secretKeyFile.isFile) return Invalid(type, true) // Disabled
}
// Load from secretKeys/$type.key
kotlin.run {
val secretKeyFile = secretKeys.resolve("$type.key").takeIf { it.isFile }
?: secretKeys.resolve("$type.key.txt")
if (secretKeyFile.isFile) {
secretKeyFile.bufferedReader().use {
fun BufferedReader.readLineNonEmpty(): String {
while (true) {
val nextLine = readLine() ?: return ""
if (nextLine.isNotBlank()) {
return nextLine.trim()
}
}
}
return SecretKeys(type, it.readLineNonEmpty(), it.readLineNonEmpty())
}
}
}
// Load from project/%type.key, user
kotlin.run {
val userFile = project.projectDir.resolve("$type.user.txt")
val keyFile = project.projectDir.resolve("$type.key.txt")
if (userFile.isFile && keyFile.isFile) {
return SecretKeys(type, userFile.readText().trim(), keyFile.readText().trim())
}
}
// Load from property $type.user, $type.password
fun findProperty(type: String): String? {
val p = project.findProperty(type)
?: System.getProperty(type)
?: System.getenv(type)
return p?.toString()
}
val tUser = findProperty("$type.user")
?: findProperty("${type}_user")
val tPassword = findProperty("$type.password")
?: findProperty("$type.passwd")
?: findProperty("$type.key")
?: findProperty("${type}_password")
?: findProperty("${type}_passwd")
?: findProperty("${type}_key")
if (tUser != null && tPassword != null) {
return SecretKeys(type, tUser, tPassword)
}
return Invalid(type)
}
}
open val isValid: Boolean get() = true
open val isDisabled: Boolean get() = false
open fun requireNotInvalid(): SecretKeys = this
}

View File

@ -7,18 +7,9 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
import keys.SecretKeys
import org.gradle.api.Project
import org.gradle.kotlin.dsl.provideDelegate
import java.io.File
/*
* Copyright 2019-2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 with Mamoe Exceptions 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 with Mamoe Exceptions license that can be found via the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
fun Project.isBintrayAvailable() = Bintray.isBintrayAvailable(project)
@Suppress("DuplicatedCode")
@ -34,76 +25,18 @@ object Bintray {
@JvmStatic
fun getUser(project: Project): String {
kotlin.runCatching {
@Suppress("UNUSED_VARIABLE", "LocalVariableName")
val bintray_user: String by project
return bintray_user
}
kotlin.runCatching {
@Suppress("UNUSED_VARIABLE", "LocalVariableName")
val bintray_user: String by project.rootProject
return bintray_user
}
System.getProperty("bintray_user", null)?.let {
return it.trim()
}
File(File(System.getProperty("user.dir")).parent, "/bintray.user.txt").let { local ->
if (local.exists()) {
return local.readText().trim()
}
}
File(File(System.getProperty("user.dir")), "/bintray.user.txt").let { local ->
if (local.exists()) {
return local.readText().trim()
}
}
error(
"Cannot find bintray user, " +
"please specify by creating a file bintray.user.txt in project dir, " +
"or by providing JVM parameter 'bintray_user'"
)
return SecretKeys.getCache(project)
.loadKey("bintray")
.requireNotInvalid()
.user
}
@JvmStatic
fun getKey(project: Project): String {
kotlin.runCatching {
@Suppress("UNUSED_VARIABLE", "LocalVariableName")
val bintray_key: String by project
return bintray_key
}
kotlin.runCatching {
@Suppress("UNUSED_VARIABLE", "LocalVariableName")
val bintray_key: String by project.rootProject
return bintray_key
}
System.getProperty("bintray_key", null)?.let {
return it.trim()
}
File(File(System.getProperty("user.dir")).parent, "/bintray.key.txt").let { local ->
if (local.exists()) {
return local.readText().trim()
}
}
File(File(System.getProperty("user.dir")), "/bintray.key.txt").let { local ->
if (local.exists()) {
return local.readText().trim()
}
}
error(
"Cannot find bintray key, " +
"please specify by creating a file bintray.key.txt in project dir, " +
"or by providing JVM parameter 'bintray_key'"
)
return SecretKeys.getCache(project)
.loadKey("bintray")
.requireNotInvalid()
.password
}
}

View File

@ -0,0 +1,22 @@
/*
* Copyright 2019-2021 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
*/
import keys.SecretKeys
plugins {
id("io.codearte.nexus-staging") version "0.22.0"
}
description = "Mirai CI Methods for Releasing"
nexusStaging {
packageGroup = rootProject.group.toString()
val keys = SecretKeys.getCache(project).loadKey("sonatype")
username = keys.user
password = keys.password
}

View File

@ -1,11 +1,12 @@
#
# Copyright 2019-2020 Mamoe Technologies and contributors.
# Copyright 2019-2021 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
#
# style guide
kotlin.code.style=official
# config
@ -17,4 +18,5 @@ org.gradle.vfs.watch=true
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false
#kotlin.mpp.enableGranularSourceSetsMetadata=true
systemProp.org.gradle.internal.publish.checksums.insecure=true
systemProp.org.gradle.internal.publish.checksums.insecure=true
gnsp.disableApplyOnlyOnRootProjectEnforcement=true

View File

@ -29,6 +29,7 @@ include(":mirai-core")
include(":mirai-core-all")
include(":binary-compatibility-validator")
include(":ci-release-helper")
fun includeConsoleProjects() {