Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/rtmigo/mavence
CLI for publishing Gradle projects (Kotlin, Java, etc.) to Maven Central
https://github.com/rtmigo/mavence
central gpg gradle java jvm kotlin maven ossrh publish reasons-to-hate-java signing sonatype
Last synced: about 2 months ago
JSON representation
CLI for publishing Gradle projects (Kotlin, Java, etc.) to Maven Central
- Host: GitHub
- URL: https://github.com/rtmigo/mavence
- Owner: rtmigo
- License: isc
- Created: 2022-10-16T22:33:31.000Z (about 2 years ago)
- Default Branch: master
- Last Pushed: 2022-10-23T23:05:19.000Z (about 2 years ago)
- Last Synced: 2023-03-11T08:51:58.678Z (almost 2 years ago)
- Topics: central, gpg, gradle, java, jvm, kotlin, maven, ossrh, publish, reasons-to-hate-java, signing, sonatype
- Language: Kotlin
- Homepage:
- Size: 257 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# [mavence](https://github.com/rtmigo/mavence) #experimental
CLI utility for publishing Gradle projects (Kotlin, Java, etc.) to Maven
Central.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 publish with plugins?
- Building locally
- Publishing somewhereThese tasks are almost unrelated.
By placing publishing logic in a build script, you make the foundation of the
project complex and ugly.# Install and run
## Command line
```
wget https://github.com/rtmigo/mavence/releases/latest/download/mavence.jar
```Run:
```
java -jar mavence.jar
```## Manually
Just get the
latest [mavence.jar](https://github.com/rtmigo/mavence/releases/latest/download/mavence.jar)
from the [releases page](https://github.com/rtmigo/mavence/releases).Run:
```
java -jar ~/Downloads/mavence.jar
```# Setting the environment
Before publishing, you will need to set the following four environment
variables:| variable | wtf |
|----------------------|-----------------------------------------------------------|
| `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. 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
It gives you `MAVEN_GPG_PASSWORD`.
```bash
$ 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
It gives you `MAVEN_GPG_KEY`.
```bash
$ gpg --list-keys
``````
pub rsa3072 2022-10-18 [SC]
1292EC426424C9BA0A581EE060C994FDCD3CADBD << this is the ID
uid [ultimate] John Doe
sub rsa3072 2022-10-18 [E]
``````bash
$ gpg --export-secret-keys --armor 1292EC426424C9BA0A581EE060C994FDCD3CADBD
``````
-----BEGIN PGP PRIVATE KEY BLOCK-----lQWGBGNOko0BDACzxxMh4EwjlOBRuV94reQglPp5Chzdw4yJHKBYffGGCy27nmde
Q05nuVbGJvHqv6jF1+zRNMIEKS/Ioa1C4jenEe0j3boGM2IgjHtPq7WuOeSR2ErX
...-----END PGP PRIVATE KEY BLOCK-----
```Or put it directly to `MAVEN_GPG_KEY` environment variable (Bash):
```bash
$ MAVEN_GPG_KEY=$(gpg --export-secret-keys --armor 1292EC426424C9BA0A581EE060C994FDCD3CADBD)$ export MAVEN_GPG_KEY
```## 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.```bash
$ gpg --list-keys
``````
pub rsa3072 2022-10-18 [SC]
1292EC426424C9BA0A581EE060C994FDCD3CADBD << this is the ID
uid [ultimate] John Doe
sub rsa3072 2022-10-18 [E]
``````bash
$ gpg --keyserver hkps://keys.openpgp.org --send-keys 1292EC426424C9BA0A581EE060C994FDCD3CADBD
```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.# 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
```kotlin
plugins {
id("java-library")
id("maven-publish")
}java {
withSourcesJar()
withJavadocJar()
}group = "my.domain"
version = "0.1.2"publishing {
publications {
create("thelib") {
from(components["java"])
pom {
val github = "https://github.com/doe/thelib"name.set("The Lib")
description.set("There are dumber things than copy-pasting")
url.set(github)developers {
developer {
name.set("John Doe")
email.set("[email protected]")
}
}
scm {
url.set(github)
connection.set(github.replace("https:", "scm:git:"))
}
licenses {
license {
name.set("Apache 2.0 License")
url.set("$github/blob/HEAD/LICENSE")
}
}
}
}
}
}
```### settings.gradle.kts
```kotlin
rootProject.name = "thelib"
```## Package name
The published package will have a version like `my.domain:thelib:0.1.2`.
Group and Version
It is the first and third part of `my.domain:thelib:0.1.2`,
i.e. `my.domain`
and `0.1.2`.They can be defined in `build.gradle.kts` like that:
```kotlin
group = "my.domain"
version = "0.1.2"
```Artifact
It is the second part of `my.domain:thelib:0.1.2`, i.e. `thelib`.
`mavence` takes it
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:
```
thelib/ <<< dir name will be the artifact name
src/
build.gradle.kts
settings.gradle.kts <<< unless redefined here
```The redefine the root project name, add the following:
```kotlin
// settings.gradle.ktsrootProject.name = "newname"
```### If we release a subproject:
```
myrootproject/
thelib/ <<< dir name will be the artifact name
src/
build.gradle.kts
settings.gradle.kts
```# Publishing
Keep in mind
When publishing, the servers may not return meaningful error responses.
They often return a generic "500 Internal Server Error" code, spontaneous
"403 Forbidden" or accept the file, but never publish it as a maven package.If publishing a package fails for any reason, sometimes this can be fixed by:
* retrying
* retrying later
* editing your package's metadata## Publish to Maven Central
Set environment variables `MAVEN_GPG_KEY`, `MAVEN_GPG_PASSWORD`
, `SONATYPE_USERNAME`, `SONATYPE_PASSWORD` and run:```
cd /path/to/thelib
java -jar mavence.jar central
```This single command will do all the necessary work: build, signing, staging
and release.### Publish to Maven Local
This will place the package file inside the local `~/.m2` directory. This way
you can
test the package without sending it anywhere.```
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`
, `SONATYPE_USERNAME`, `SONATYPE_PASSWORD` and run:```
cd /path/to/thelib
java -jar mavence.jar stage
```This will push the package to
a [temporary remote repository](https://s01.oss.sonatype.org/content/repositories/)
.
This way you can test the package without sending it to Central.## Testing before publishing
Although the utility prints quite a lot, `stdout` remains clean and only
receives the result as JSON.Bash:
```
JSON=$(java -jar mavence.jar local)echo $JSON
```Output:
```json
{
"group": "my.domain",
"artifact": "thelib",
"version": "0.1.2",
"notation": "my.domain:thelib:0.1.2",
"mavenRepo": "file:///home/doe/.m2/repository"
}
```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
Copyright © 2022 [Artsiom iG](https://github.com/rtmigo).
Released under the [ISC License](LICENSE).