Перейти к содержимому

Публикация в Maven

Публикуйте JVM-библиотеки с elide publish: установка в локальный репозиторий Maven, развёртывание в Nexus, Artifactory или GitHub Packages и выпуск в Maven Central с подписями и контрольными суммами, без плагинов.

На этой странице

elide publish собирает JAR-файлы библиотеки, пишет POM для её потребителей и публикует их в репозиторий Maven: по умолчанию в локальный, с --to — в репозиторий команды, или в Maven Central через Central Publisher Portal. После этого Maven, Gradle и другие проекты Elide зависят от неё, как от любого другого артефакта. Публикацию настраивает блок publishing в elide.pkl; добавлять плагины не нужно.

ЦельКомандаЧто нужно
Локальный репозиторий Mavenelide publishgroupId, version, один Jar
Репозиторий командыelide publish --to internalУчётные данные в окружении
Maven Centralelide publish --to centralТокен Portal, gpg, метаданные POM, JAR с исходниками и javadoc
Никуда (сначала проверить)elide publish --dry-runНичего

Локальная установка

Публикации нужны groupId, version проекта и один артефакт Jvm.Jar:

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 publish

Elide собирает JAR (повторно используя актуальные результаты), пишет POM и устанавливает оба файла как dev.example:greeter:1.0.0 в ~/.m2/repository вместе с maven-metadata-local.xml. По умолчанию artifactId — это имя проекта. Повторная установка той же версии заменяет её, поэтому потребитель на той же машине получает каждое изменение. Из Maven:

<dependency>
  <groupId>dev.example</groupId>
  <artifactId>greeter</artifactId>
  <version>1.0.0</version>
</dependency>

Из Gradle:

repositories { mavenLocal() }
dependencies { implementation("dev.example:greeter:1.0.0") }

Из другого проекта Elide:

dependencies {
  maven {
    packages { "dev.example:greeter:1.0.0" }
  }
}

Локальной установке не нужны ни сеть, ни учётные данные. localRepository задаёт другое место установки; относительный путь разрешается относительно манифеста.

Проверка перед публикацией

elide publish --dry-run

--dry-run подготавливает POM и JAR-файлы в .dev/staging/publish/maven с именами файлов Maven (greeter-1.0.0.jar, greeter-1.0.0-sources.jar, greeter-1.0.0.pom) и выводит их список. Если подпись включена, он подписывает их, а для Maven Central также пишет бандл, поэтому показывает ровно то, что отправил бы настоящий запуск. В репозиторий ничего не записывается.

Что попадает в POM

POM описывает библиотеку для потребителей, а не сборку: координаты, метаданные pom и зависимости, без <build>, <repositories> и локальных путей.

elide.pklОпубликованный POM
packages, modulesЗависимости compile
runtimeOnlyЗависимости runtime
compileOnly, devPackages, processors, kotlinPlugins, testPackagesНе попадают
exclusions без версии<exclusion> у каждой зависимости
Проект рабочего пространстваКоординаты публикации этого проекта
Соседний проект в Jar.fromЕго packages, modules и runtimeOnly, если их ещё нет в списке
Путь к локальному JARОшибка: потребители не смогут его разрешить

Библиотеки на Kotlin

POM также перечисляет то, что Elide добавляет в classpath Kotlin-проекта без объявления, потому что это нужно потребителям во время выполнения: kotlin-stdlib и kotlin-reflect версии Kotlin проекта, а также библиотеки времени выполнения, которые включает kotlin.features (корутины, сериализация). Чтобы закрепить другую версию, отключите функцию, задайте kotlin.compilerOptions.noStdlib или объявите зависимость сами.

По умолчанию публикация содержит все Jar, SourceJar и JavadocJar, объявленные в проекте; artifacts выбирает подмножество по именам артефактов. В ней должен быть ровно один Jar и не больше одного артефакта на каждый классификатор. JavadocJar для исходников на Kotlin генерируется с помощью Dokka (см. Сборка JAR).

Публикация в репозиторий команды

Задайте имя репозитория в repositories, а затем публикуйте в него по этому имени:

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 internal

Учётные данные берутся из ELIDE_MAVEN_<NAME>_USERNAME и ELIDE_MAVEN_<NAME>_PASSWORD, где <NAME> — имя репозитория в верхнем регистре, в котором все прочие символы заменены на _ (my-repo → ELIDE_MAVEN_MY_REPO_…), поэтому манифест не хранит секретов. Каждый файл загружается с контрольными суммами .md5, .sha1, .sha256 и .sha512, а maven-metadata.xml обновляется. Это работает с Nexus, Artifactory, GitHub Packages и любым репозиторием, который принимает загрузки Maven. Обычный URL http://, кроме localhost, отклоняется без --allow-http-repositories.

Подпись с помощью gpg

publishing {
  maven {
    signing { gpg { keyName = "0123ABCD" } }   // `signing {}` uses gpg's default key
  }
}

Если задан signing, при публикации в удалённый репозиторий каждый файл подписывается программой gpg (<file>.asc). Локальная установка подписывает только с --sign; --no-sign отключает подпись. Парольную фразу запрашивает gpg-agent; в CI задайте ELIDE_GPG_PASSPHRASE, и Elide передаст её в gpg через loopback pinentry. Elide никогда не читает ключ сам. Если gpg отсутствует или завершается с ошибкой, ничего не публикуется.

Выпуск в Maven Central

Maven Central требует метаданные POM, JAR с исходниками и javadoc, подписи и релизную версию. Полная библиотека:

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 {}
    }
  }
}

Создайте пользовательский токен в Central Publisher Portal и опубликуйте:

export ELIDE_MAVEN_CENTRAL_USERNAME=<token user>
export ELIDE_MAVEN_CENTRAL_PASSWORD=<token password>
elide publish --to central

До начала сборки Elide проверяет требования Central и сообщает обо всём недостающем сразу: name, description, url, licenses, developers и scm.url в POM, SourceJar, JavadocJar и версию, которая не является -SNAPSHOT. По умолчанию description в POM берётся из проекта. Публикация в Central всегда подписывается ключом gpg по умолчанию, если signing не выбирает другой, поэтому --no-sign отклоняется.

Elide загружает один подписанный бандл с контрольными суммами и ждёт, пока Portal его проверит. По умолчанию (publishingType = "USER_MANAGED") вы затем выпускаете развёртывание в Portal; Elide выводит ссылку на его страницу. С publishingType = "AUTOMATIC" Portal выпускает его сам после проверки. Если проверка не прошла, Elide выводит ошибки Portal. --no-wait завершает работу сразу после загрузки.

Рабочие пространства

В рабочем пространстве задайте общую конфигурацию один раз в корневом 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 {} }
  }
}

Участники наследуют всё, кроме artifactId и artifacts, которые задаются для каждого проекта отдельно; собственные настройки участника имеют приоритет по каждому полю, а репозитории объединяются по имени.

ЗапускПубликует
elide publish в корнеВсе проекты
elide publish в участникеЭтого участника и все проекты рабочего пространства, от которых зависит его POM
elide publish core utilРовно core и util; проекты рабочего пространства, от которых они зависят, уже должны быть в целевом репозитории
elide publish --skip-existingВсе выбранные проекты, версии которых ещё нет в целевом репозитории

Все проекты собираются, подготавливаются и подписываются до публикации первого из них, поэтому сбой на этих этапах ничего не публикует. В Maven Central все проекты попадают в одно развёртывание, которое Portal проверяет и выпускает целиком. --skip-existing также позволяет перезапустить выпуск, прервавшийся на полпути: он пропускает то, что уже опубликовано, и никогда не пропускает снапшот.

В 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 }}

Импортируйте ключ подписи в связку ключей gpg раннера на одном из предыдущих шагов. Как установить Elide на раннер, описано в разделе Непрерывная интеграция.

Справочник

Была ли эта страница полезной?