elide publish builds a library’s JARs, writes a POM for its consumers and publishes them to a Maven repository: the
local one by default, a team repository with --to, or Maven Central through the Central Publisher Portal. Maven,
Gradle and other Elide projects then depend on it like any other artifact. The publishing block in elide.pkl
configures it; there are no plugins to add.
| Target | Command | Needs |
|---|---|---|
| Local Maven repository | elide publish | groupId, version, one Jar |
| A team repository | elide publish --to internal | Credentials in the environment |
| Maven Central | elide publish --to central | Portal token, gpg, POM metadata, sources and javadoc JARs |
| Nowhere (check first) | elide publish --dry-run | Nothing |
Install locally
A publication needs a groupId, the project’s version and one Jvm.Jar artifact:
amends "elide:project.pkl"
import "elide:Jvm.pkl" as Jvm
name = "greeter"
version = "1.0.0"
description = "Greets people."
artifacts {
["lib"] = new Jvm.Jar {}
}
publishing {
maven {
groupId = "dev.example"
}
}elide publishElide builds the JAR (reusing up-to-date outputs), writes the POM and installs both as dev.example:greeter:1.0.0
under ~/.m2/repository, with maven-metadata-local.xml. The artifactId defaults to the project name. Reinstalling
the same version replaces it, so a consumer on the same machine picks up each change. From Maven:
<dependency>
<groupId>dev.example</groupId>
<artifactId>greeter</artifactId>
<version>1.0.0</version>
</dependency>From Gradle:
repositories { mavenLocal() }
dependencies { implementation("dev.example:greeter:1.0.0") }From another Elide project:
dependencies {
maven {
packages { "dev.example:greeter:1.0.0" }
}
}A local install needs no network and no credentials. localRepository installs somewhere else; a relative path
resolves against the manifest.
Check before publishing
elide publish --dry-run--dry-run stages the POM and JARs under .dev/staging/publish/maven with Maven file names
(greeter-1.0.0.jar, greeter-1.0.0-sources.jar, greeter-1.0.0.pom) and lists them. It signs them when signing is
on, and for Maven Central also writes the bundle, so it shows exactly what a real run would send. Nothing is written
to a repository.
What goes in the POM
The POM describes the library for its consumers, not the build: coordinates, the pom metadata and dependencies,
with no <build>, <repositories> or local paths.
elide.pkl | Published POM |
|---|---|
packages, modules | compile dependencies |
runtimeOnly | runtime dependencies |
compileOnly, devPackages, processors, kotlinPlugins, testPackages | Left out |
Versionless exclusions | An <exclusion> on every dependency |
| A workspace project | That project’s publishing coordinates |
A Jar.from sibling | Its packages, modules and runtimeOnly, unless already listed |
| A local JAR path | An error: consumers can’t resolve it |
Kotlin libraries
The POM also lists what Elide adds to a Kotlin project’s classpath without a declaration, because consumers need it
at run time: kotlin-stdlib and kotlin-reflect at the project’s Kotlin version, and the runtimes
kotlin.features turns on (coroutines, serialization). Turn a feature off, set kotlin.compilerOptions.noStdlib, or
declare the dependency yourself to pin another version.
By default a publication holds every Jar, SourceJar and JavadocJar the project declares; artifacts picks a
subset by artifact name. It must contain exactly one Jar, and each classifier once. A JavadocJar over Kotlin
sources is generated with Dokka (see JAR assembly).
Publish to a team repository
Name the repository under repositories, then publish to it by name:
publishing {
maven {
groupId = "dev.example"
repositories {
["internal"] = "https://repo.example.dev/releases"
}
}
}export ELIDE_MAVEN_INTERNAL_USERNAME=ci
export ELIDE_MAVEN_INTERNAL_PASSWORD="$REPO_TOKEN"
elide publish --to internalCredentials come from ELIDE_MAVEN_<NAME>_USERNAME and ELIDE_MAVEN_<NAME>_PASSWORD, where <NAME> is the
repository name in upper case with every other character turned into _ (my-repo → ELIDE_MAVEN_MY_REPO_…), so
the manifest holds no secrets. Every file is uploaded with .md5, .sha1, .sha256 and .sha512 checksums, and
maven-metadata.xml is updated. This works with Nexus, Artifactory, GitHub Packages and any repository that accepts
Maven uploads. A plain http:// URL other than localhost is refused without --allow-http-repositories.
Sign with gpg
publishing {
maven {
signing { gpg { keyName = "0123ABCD" } } // `signing {}` uses gpg's default key
}
}With signing set, a remote publish signs every file with the gpg binary (<file>.asc). A local install signs only
with --sign; --no-sign turns signing off. gpg-agent asks for the passphrase; in CI, set ELIDE_GPG_PASSPHRASE
and Elide passes it to gpg through loopback pinentry. Elide never reads the key itself. If gpg is missing or fails,
nothing is published.
Release to Maven Central
Maven Central needs POM metadata, sources and javadoc JARs, signatures and a release version. A complete library:
amends "elide:project.pkl"
import "elide:Jvm.pkl" as Jvm
import "elide:Publishing.pkl" as Publishing
name = "greeter"
version = "1.0.0"
description = "Greets people."
artifacts {
["lib"] = new Jvm.Jar {}
["sources"] = new Jvm.SourceJar {}
["javadoc"] = new Jvm.JavadocJar {}
}
publishing {
maven {
groupId = "dev.example"
pom {
name = "Greeter"
url = "https://github.com/example/greeter"
licenses { new { name = "Apache-2.0"; url = "https://www.apache.org/licenses/LICENSE-2.0" } }
developers { new { id = "jdoe"; name = "J. Doe" } }
scm { url = "https://github.com/example/greeter" }
}
repositories {
["central"] = new Publishing.CentralPortal {}
}
}
}Create a user token in the Central Publisher Portal and publish:
export ELIDE_MAVEN_CENTRAL_USERNAME=<token user>
export ELIDE_MAVEN_CENTRAL_PASSWORD=<token password>
elide publish --to centralBefore building anything, Elide checks Central’s requirements and reports everything missing at once: the POM’s
name, description, url, licenses, developers and scm.url, a SourceJar, a JavadocJar, and a version that
isn’t a -SNAPSHOT. The POM’s description defaults to the project’s. Central always signs, with gpg’s default key
unless signing picks one, so --no-sign is refused.
Elide uploads one signed, checksummed bundle and waits for the Portal to validate it. By default
(publishingType = "USER_MANAGED") you then release the deployment in the Portal; Elide prints its page. With
publishingType = "AUTOMATIC" the Portal releases it once validated. A failed validation prints the Portal’s errors.
--no-wait returns right after the upload.
Workspaces
In a workspace, set the shared configuration once in the root elide.pkl:
import "elide:Publishing.pkl" as Publishing
publishing {
maven {
groupId = "dev.example"
pom { url = "https://github.com/example/greeter"; scm { url = "https://github.com/example/greeter" } }
repositories { ["central"] = new Publishing.CentralPortal {} }
}
}Members inherit everything except artifactId and artifacts, which stay per project; a member’s own settings win
field by field, and repositories merge by name.
| Run | Publishes |
|---|---|
elide publish at the root | Every project |
elide publish in a member | That member and every workspace project its POM depends on |
elide publish core util | Exactly core and util; workspace projects they depend on must already be in the target |
elide publish --skip-existing | Every selected project whose version isn’t in the target yet |
Every project is built, staged and signed before any is published, so a failure there publishes nothing. To Maven
Central, every project goes into one deployment that the Portal validates and releases together. --skip-existing
also reruns a release that failed partway: it leaves out what already made it, and never skips a snapshot.
In CI
- run: elide publish --to central --skip-existing
env:
ELIDE_MAVEN_CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }}
ELIDE_MAVEN_CENTRAL_PASSWORD: ${{ secrets.CENTRAL_PASSWORD }}
ELIDE_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}Import the signing key into the runner’s gpg keyring in an earlier step. See Continuous integration
to install Elide on the runner.
Reference
elide publish: every flag.publishing: every manifest property.- POM export: print a
pom.xmlfor the build instead of publishing.