diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 83bd178..11c819a 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -177,8 +177,8 @@ jobs:
echo "result=$VERSION" >>$GITHUB_OUTPUT
- name: Build
run: |
- #export GPG_TTY=$(tty)
./gradlew uberJar
+ java -jar ./build/libs/mavence.uber.jar --version
mv ./build/libs/mavence.uber.jar ./build/libs/mavence.jar
env:
MAVEN_GPG_KEY: ${{ secrets.MAVEN_GPG_KEY }}
diff --git a/README.md b/README.md
index 823f5c7..547604b 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,8 @@ This essentially does the same thing as
the [Signing](https://docs.gradle.org/current/userguide/signing_plugin.html) and
[Nexus](https://github.com/gradle-nexus/publish-plugin) plugins.
-Why not use plugins?
+Why not publish with plugins?
+
- Building locally
- Publishing somewhere
@@ -15,16 +16,13 @@ the [Signing](https://docs.gradle.org/current/userguide/signing_plugin.html) and
These tasks are almost unrelated.
By placing publishing logic in a build script, you make the foundation of the
-project complex, big and ugly.
-
-However, we still use some Gradle plugins. The `maven-publish` creates, i.e.
-builds a local copy of the Maven package.
+project complex and ugly.
-## Install and run
+# Install and run
-### Command line
+## Command line
```
wget https://github.com/rtmigo/mavence/releases/latest/download/mavence.jar
@@ -36,8 +34,7 @@ Run:
java -jar mavence.jar
```
-
-### Manually
+## Manually
Just get the
latest [mavence.jar](https://github.com/rtmigo/mavence/releases/latest/download/mavence.jar)
@@ -49,23 +46,39 @@ Run:
java -jar ~/Downloads/mavence.jar
```
-
-
-## Setting the environment
+# Setting the environment
Before publishing, you will need to set the following four environment
variables:
| variable | wtf |
|----------------------|-----------------------------------------------------------|
-| `MAVEN_GPG_KEY` | Locally generated private key in ASCII armor |
-| `MAVEN_GPG_PASSWORD` | Password protecting the private key |
| `SONATYPE_USERNAME` | Username for Sonatype JIRA (optionally replaced by token) |
| `SONATYPE_PASSWORD` | Password for Sonatype JIRA (optionally replaced by token) |
+| `MAVEN_GPG_KEY` | Locally generated private key in ASCII armor |
+| `MAVEN_GPG_PASSWORD` | Password protecting the private key |
+
+Where to get Sonatype variables
+
+[Register](https://getstream.io/blog/publishing-libraries-to-mavencentral-2021/#registering-a-sonatype-account)
+on the [Sonatype Jira](https://issues.sonatype.org/secure/Dashboard.jspa)
+and chat with bots, 🤪 until they **verify** that you can publish a package.
+That gives you `SONATYPE_USERNAME` and `SONATYPE_PASSWORD` you can use for
+publishing.
+
+Additionally, you
+can [generate tokens](https://central.sonatype.org/publish/manage-user/#generate-token-on-nxrm-servers)
+to use them instead of the username and password (tokens are safer). The
+tokens can be placed in the same `SONATYPE_USERNAME` and `SONATYPE_PASSWORD` and
+do not require other changes.
+
+**May the Google be with you.**
+
+
Where to get GPG variables
-### Generate key
+## Generate key
It gives you `MAVEN_GPG_PASSWORD`.
@@ -76,7 +89,7 @@ $ gpg --gen-key
`gpg` will interactively prompt you to choose a password for the new key. It is
this password that should later be placed in the variable `MAVEN_GPG_PASSWORD`.
-### See your private key
+## See your private key
It gives you `MAVEN_GPG_KEY`.
@@ -113,7 +126,7 @@ $ MAVEN_GPG_KEY=$(gpg --export-secret-keys --armor 1292EC426424C9BA0A581EE060C99
$ export MAVEN_GPG_KEY
```
-### Send the public key to [a keyserver](https://unix.stackexchange.com/a/692097)
+## Send the public key to [a keyserver](https://unix.stackexchange.com/a/692097)
You won't come back to this again, but it will be important for the servers when
publishing the package.
@@ -136,36 +149,14 @@ $ gpg --keyserver hkps://keys.openpgp.org --send-keys 1292EC426424C9BA0A581EE060
Some servers will just store the key. Some may require prior email verification.
Some servers disappear. You have to choose the right one for the moment.
-
-
-
-Where to get Sonatype variables
-
-You need
-to [register](https://getstream.io/blog/publishing-libraries-to-mavencentral-2021/#registering-a-sonatype-account)
-on the [Sonatype Jira](https://issues.sonatype.org/secure/Dashboard.jspa)
-and chat with bots, until they **verify** that you can publish a package.
-That gives you `SONATYPE_USERNAME` and `SONATYPE_PASSWORD` you can use for
-publishing.
-
-If you have enough nerve for one more step, you
-can [generate tokens](https://central.sonatype.org/publish/manage-user/#generate-token-on-nxrm-servers)
-.
-The tokens also can be placed in the `SONATYPE_USERNAME` and `SONATYPE_PASSWORD`
-. In some circumstances it is safer.
-
-
-
-
-
-## Minimal configuration
+# Minimal configuration
We're using Gradle configuration to build a Maven package, but not push
it Central. Creating in this way seems like a reasonable compromise.
-#### build.gradle.kts
+### build.gradle.kts
```kotlin
plugins {
@@ -199,7 +190,10 @@ publishing {
}
}
scm {
- connection.set(github.replace("https:", "scm:git:") + ".git")
+ connection.set(
+ github.replace(
+ "https:",
+ "scm:git:") + ".git")
url.set(github)
}
licenses {
@@ -214,13 +208,13 @@ publishing {
}
```
-#### settings.gradle.kts
+### settings.gradle.kts
```kotlin
rootProject.name = "thelib"
```
-### Package name
+## Package name
The published package will have a version like `my.domain:thelib:0.1.2`.
@@ -247,7 +241,7 @@ It is the second part of `my.domain:thelib:0.1.2`, i.e. `thelib`.
from [archivesBaseName](https://docs.gradle.org/current/dsl/org.gradle.api.Project.html#org.gradle.api.Project:archivesBaseName)
Gradle property.
-#### If we release the root project:
+### If we release the root project:
```
thelib/ <<< dir name will be the artifact name
@@ -264,7 +258,7 @@ The redefine the root project name, add the following:
rootProject.name = "newname"
```
-#### If we release a subproject:
+### If we release a subproject:
```
myrootproject/
@@ -276,18 +270,23 @@ myrootproject/
-## Keep in mind
+
+
+# Publishing
+
+Keep in mind
When publishing, the servers may not return meaningful error responses. They
often return a generic "500 Internal Server Error" code, or accept the file, but
never publish it as a maven package.
If publishing a package fails for any reason, the problem may be in the meta
-data. Something does not match with something: package name, authors, signatures.
+data. Something does not match with something: package name, authors,
+signatures.
-## Publishing
+
-### Publish to Maven Central
+## Publish to Maven Central
Set environment variables `MAVEN_GPG_KEY`, `MAVEN_GPG_PASSWORD`
, `SONATYPE_USERNAME`, `SONATYPE_PASSWORD` and run:
@@ -311,6 +310,20 @@ cd /path/to/thelib
java -jar mavence.jar local
```
+stdout
+
+```
+{
+ "group": "my.domain",
+ "artifact": "thelib",
+ "version": "0.1.2",
+ "notation": "my.domain:thelib:0.1.2",
+ "mavenRepo": "file:///home/doe/.m2/repository"
+}
+```
+
+
+
### Publish to Staging
Set environment variables `MAVEN_GPG_KEY`, `MAVEN_GPG_PASSWORD`
@@ -356,7 +369,7 @@ Using this data, you can test the package before it is sent.
I usually use Python and [tempground](https://pypi.org/project/tempground/) for
such testing.
-## License
+# License
Copyright © 2022 [Artsiom iG](https://github.com/rtmigo).
Released under the [ISC License](LICENSE).
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 5a1ec5f..380b74e 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -9,7 +9,7 @@ plugins {
}
group = "io.github.rtmigo"
-version = "0.2.0" // -SNAPSHOT
+version = "0.3.0" // -SNAPSHOT
repositories {
mavenCentral()
diff --git a/src/main/kotlin/Build.kt b/src/main/kotlin/Build.kt
index 0ca8505..f78d114 100644
--- a/src/main/kotlin/Build.kt
+++ b/src/main/kotlin/Build.kt
@@ -1,5 +1,5 @@
// DO NOT EDIT. Generated by Gradle task "generateBuildKt"
object Build {
- const val version = "0.2.0"
- const val date = "2022-10-20"
+ const val version = "0.3.0"
+ const val date = "2022-10-21"
}
\ No newline at end of file
diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt
index 6fa03a2..70ab487 100644
--- a/src/main/kotlin/Main.kt
+++ b/src/main/kotlin/Main.kt
@@ -12,12 +12,15 @@ import stages.build.*
import stages.sign.*
import stages.upload.*
import java.nio.file.*
+import kotlin.io.path.absolute
class Cli : NoOpCliktCommand(
name = "mavence",
help = "Publishes Gradle projects to Maven Central\n\nSee: https://github.com/rtmigo/mavence#readme"
) {
+ private val trace by option("--trace", help = "Show full stack traces on errors").flag()
+
init {
versionOption(Build.version) {
"$commandName $it (${Build.date})\n" +
@@ -26,21 +29,20 @@ class Cli : NoOpCliktCommand(
}
}
- override fun run() = Unit
+ override fun run() {
+ currentContext.findOrSetObject { CliConfig(trace = this.trace) }
+ }
}
private suspend fun gaa(): GroupArtifact {
- val ad = ArtifactDir(Paths.get("."))
+ val ad = ArtifactDir(Paths.get(".").absolute())
return GroupArtifact(ad.group(), ad.artifact())
}
-open class Local(help: String="Build, publish to $m2str") : CliktCommand(help = help) {
- //val groupAndArtifact by argument("")
+data class CliConfig(val trace: Boolean)
- override fun run() = runBlocking {
- //val gw = Paths.get(".").toGradlew()
- //gw.
- //val ad = ArtifactDir(Paths.get("."))
+open class Local(help: String = "Build, publish to $m2str") : CliktCommand(help = help) {
+ override fun run() = catchingCommand(this) {
cmdLocal(gaa(), isFinal = true)
Unit
}
@@ -58,7 +60,7 @@ open class Stage(help: String = "Build, sign, publish to OSSRH Staging") :
"--sonatype-password",
envvar = "SONATYPE_PASSWORD").required()
- override fun run() = runBlocking {
+ override fun run() = catchingCommand(this) {
cmdSign(
cmdLocal(gaa()),
key = GpgPrivateKey(gpgKey),
@@ -74,7 +76,7 @@ open class Stage(help: String = "Build, sign, publish to OSSRH Staging") :
}
class Central : Stage(help = "Build, sign, publish to OSSRH Staging, release to Central") {
- override fun run() = runBlocking {
+ override fun run() = catchingCommand(this) {
cmdSign(
cmdLocal(gaa()),
key = GpgPrivateKey(gpgKey),
@@ -90,6 +92,21 @@ class Central : Stage(help = "Build, sign, publish to OSSRH Staging, release to
}
}
+fun catchingCommand(cmd: CliktCommand, block: suspend () -> Unit) {
+ try {
+ runBlocking {
+ block()
+ }
+ } catch (e: Exception) {
+ if (cmd.currentContext.findObject()!!.trace)
+ e.printStackTrace()
+ else
+ System.err.println("ERROR: $e")
+ System.err.println("Run with --trace to see full stack trace.")
+ }
+
+}
+
fun main(args: Array) {
Cli()
.subcommands(Local(), Stage(), Central())
diff --git a/src/main/kotlin/stages/build/Building.kt b/src/main/kotlin/stages/build/Building.kt
index 6a00cbf..f628177 100644
--- a/src/main/kotlin/stages/build/Building.kt
+++ b/src/main/kotlin/stages/build/Building.kt
@@ -13,7 +13,7 @@ import kotlin.io.path.*
suspend fun cmdLocal(ga: GroupArtifact, isFinal: Boolean = false): MavenArtifactDir {
eprintHeader("Publishing to $m2str")
- val f = Paths.get(".")
+ val f = Paths.get(".").absolute()
.toGradlew().publishAndDetect(ga,null)
eprint()
@@ -22,7 +22,7 @@ suspend fun cmdLocal(ga: GroupArtifact, isFinal: Boolean = false): MavenArtifact
fun debugReplace(fn: String) {
// In case Sonatype freezes or gives uninformative errors, we can try to debug by
// replacing files one at a time. Normally it does not run
- val src = Paths.get("...")
+ val src = Paths.get("---")
println("HACKY REPLACE $fn")
val srcFile = src.resolve(fn)
val dstFile = mad.path.resolve(fn)
diff --git a/src/main/kotlin/stages/build/GradleTypes.kt b/src/main/kotlin/stages/build/GradleTypes.kt
index 2c49084..a96d94a 100644
--- a/src/main/kotlin/stages/build/GradleTypes.kt
+++ b/src/main/kotlin/stages/build/GradleTypes.kt
@@ -6,6 +6,10 @@
import java.nio.file.Path
import kotlin.io.path.*
+//class AbsPath(src: Path) {
+// val path: Path = src.absolute()
+//}
+
@JvmInline
value class ProjectRootDir(val path: Path) {
init {
@@ -16,6 +20,7 @@ value class ProjectRootDir(val path: Path) {
@JvmInline
value class ArtifactDir(val path: Path) {
init {
+ require(path.isAbsolute)
require(
path.resolve("build.gradle.kts").exists() ||
path.resolve("build.gradle").exists()) {
diff --git a/src/main/kotlin/stages/sign/GpgTty.kt b/src/main/kotlin/stages/sign/GpgTty.kt
index 03b0474..21a6eb5 100644
--- a/src/main/kotlin/stages/sign/GpgTty.kt
+++ b/src/main/kotlin/stages/sign/GpgTty.kt
@@ -1,3 +1,8 @@
+/**
+ * SPDX-FileCopyrightText: (c) 2022 Artsiom iG (rtmigo.github.io)
+ * SPDX-License-Identifier: ISC
+ **/
+
package stages.sign
import com.github.pgreze.process.process
diff --git a/src/main/kotlin/stages/upload/Bundle.kt b/src/main/kotlin/stages/upload/Bundle.kt
index eb280f8..7f25d0f 100644
--- a/src/main/kotlin/stages/upload/Bundle.kt
+++ b/src/main/kotlin/stages/upload/Bundle.kt
@@ -42,4 +42,3 @@ class SignedBundle(val jar: Path, private val tempDir: CloseableTempDir) : Close
tempDir.close()
}
}
-
diff --git a/src/main/kotlin/stages/upload/Http.kt b/src/main/kotlin/stages/upload/Http.kt
index 6405ffd..41acb64 100644
--- a/src/main/kotlin/stages/upload/Http.kt
+++ b/src/main/kotlin/stages/upload/Http.kt
@@ -190,6 +190,12 @@ suspend fun HttpClient.waitForUri(
private val json = Json { encodeDefaults = true }
suspend fun HttpClient.promoteToCentral(uri: StagingUri) {
+
+ // иногда тут бывает
+ // Error: Exception in thread "main" java.lang.IllegalStateException: Failed to promote:
+ // 500 Server Error
+ // {"errors":[{"id":"*","msg":"Unhandled: Staging repository is already transitioning: iogithubrtmigo-1183"}]}
+
eprintHeader("Promoting Staging to Release")
this.post("https://s01.oss.sonatype.org/service/local/staging/bulk/promote") {
setBody(
diff --git a/src/main/kotlin/tools/Thrower.kt b/src/main/kotlin/tools/Thrower.kt
index a17e241..31e30e0 100644
--- a/src/main/kotlin/tools/Thrower.kt
+++ b/src/main/kotlin/tools/Thrower.kt
@@ -1,25 +1,12 @@
package tools
-import java.lang.IllegalStateException
-
-//inline fun rethrowing(
-// error: () -> Throwable,
-// call: () -> R,
-//): R {
-// try {
-// return call()
-// } catch (e: Throwable) {
-// throw error()
-// }
-//}
-
inline fun rethrowingState(
error: () -> String,
call: () -> R,
): R {
try {
return call()
- } catch (e: Throwable) {
+ } catch (e: Exception) {
throw IllegalStateException(error(), e)
}
}
\ No newline at end of file
diff --git a/src/test/kotlin/GradleTest.kt b/src/test/kotlin/GradleTest.kt
index 8983202..aec6028 100644
--- a/src/test/kotlin/GradleTest.kt
+++ b/src/test/kotlin/GradleTest.kt
@@ -4,21 +4,22 @@ import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Test
import stages.build.*
import java.nio.file.*
+import kotlin.io.path.absolute
class GradleTest {
@Test
fun testVersion() = runBlocking {
- Paths.get(".").toGradlew().getGradleVersion()[0].isDigit().shouldBeTrue()
+ Paths.get(".").absolute().toGradlew().getGradleVersion()[0].isDigit().shouldBeTrue()
}
@Test
fun testProperties() = runBlocking {
- ArtifactDir(Paths.get(".")).gradleVersion()[0].isDigit().shouldBeTrue()
+ ArtifactDir(Paths.get(".").absolute()).gradleVersion()[0].isDigit().shouldBeTrue()
}
@Test
fun testOwnDependencies() = runBlocking {
- val x = ArtifactDir(Paths.get(".")).dependencies("runtimeClasspath")
+ val x = ArtifactDir(Paths.get(".").absolute()).dependencies("runtimeClasspath")
x.filter { it.notation.artifact.string=="kotlin-stdlib-jdk8" }.size.shouldBe(1)
}
}
\ No newline at end of file