Как плагин может программно настроить публикацию публикации maven-publish и разрешить build.gradle изменять ее
У меня есть общие настройки проекта в плагине, называемом родительским, который пытается применить плагин maven-publish и затем программно настроить расширение публикации. Это похоже на работу, но когда я применяю этот плагин в файле build.gradle script, я не могу настроить расширение публикации, чтобы устанавливать публикации, связанные с проектом.
Я получаю сообщение об ошибке:
Cannot configure the 'publishing' extension after it has been accessed.
Мое намерение состояло в том, чтобы создать репозиторий публикации в родительском плагине, а затем позволить каждому build.gradle script добавлять соответствующие публикации.
Есть ли способ сделать это?
В настоящее время ParentPlugin.groovy выглядит так:
def void apply(Project project) {
project.getProject().apply plugin: 'maven-publish'
def publishingExtension = project.extensions.findByName('publishing')
publishingExtension.with {
repositories {
maven {
mavenLocal()
credentials {
username getPropertyWithDefault(project.getProject(), 'publishUserName', 'dummy')
password getPropertyWithDefault(project.getProject(), 'publishPassword', 'dummy')
}
}
}
}
}
Мой клиент build.gradle терпит неудачу, когда он пытается настроить расширение публикации.
apply plugin: 'parent'
publishing {
publications {
mavenJava(MavenPublication) {
groupId 'agroup'
artifactId 'anartifactid'
version '1.0.0-SNAPSHOT'
from components.java
}
}
}
Возможно ли это? Есть ли другой способ, которым я должен приближаться к этому?
Ответы
Ответ 1
Чтобы справиться с этим, я написал еще один плагин, который может задержать модификации публикации, а также избежать "чтения" расширения, которое поместило бы его в "настроенное" состояние. Плагин называется туманным-издательским плагином, код для "ленивого" блока можно найти в github repo. Это выглядит так:
/**
* All Maven Publications
*/
def withMavenPublication(Closure withPubClosure) {
// New publish plugin way to specify artifacts in resulting publication
def addArtifactClosure = {
// Wait for our plugin to be applied.
project.plugins.withType(PublishingPlugin) { PublishingPlugin publishingPlugin ->
DefaultPublishingExtension publishingExtension = project.getExtensions().getByType(DefaultPublishingExtension)
publishingExtension.publications.withType(MavenPublication, withPubClosure)
}
}
// It possible that we're running in someone else afterEvaluate, which means we need to run this immediately
if (project.getState().executed) {
addArtifactClosure.call()
} else {
project.afterEvaluate addArtifactClosure
}
}
Вы бы тогда назовите его следующим образом:
withMavenPublication { MavenPublication t ->
def webComponent = project.components.getByName('web')
// TODO Include deps somehow
t.from(webComponent)
}
Плагин доступен в jcenter() как "com.netflix.nebula: туманность-публикация-плагин: 1.9.1".
Ответ 2
ПРИМЕЧАНИЕ относительно репозиториев {} и публикаций {} для плагина maven-publish:
Тема: Как обмануть это недоумение gradle фатальное сообщение об ошибке: Невозможно настроить расширение "публикации" после его доступа
Первое, что нужно попробовать (глубокая магия):
(примечание "проект." префикс является необязательным)
- Настроить публикации и хранилища не так:
project.publishing {publications {...}}
project.publishing {repositories {...}}
но вместо этого рекомендуется этот стиль:
project.publishing.publications {...}
project.publishing.repositories {...}
Было бы поучительно для гуру gradle объяснить, почему этот трюк работает.
Еще одно известное решение - убедиться, что каждое приложение плагина
maven-publish находится в том же блоке кода проекта, что и
project.publishing.repositories и project.publishing.publications.
Но это сложнее и сложнее, чем первое, что нужно попробовать,
поскольку по умолчанию CBF применяет maven-publish и второе применение
может сама вызвать ту же ошибку.
maven-publish обычно применяется в pub/scripts/publish-maven.gradle,
если PUB_PUBLISH_MAVEN не будет переопределять это местоположение файла,
в этом случае вызывающий должен применять плагин maven-publish.
См. https://orareview.us.oracle.com/29516818, как это неприемлемо
обходное решение может быть выполнено (для проектных emcapms) при использовании CBF.
P.S. Когда-нибудь я напишу это с минимальными примерами кода. Но сейчас я помещаю это трудно завоеванное знание, чтобы спасти других людей от траты времени на эту общую проблему публикации в maven.
Ответ 3
Немного поздно, но я нашел решение, для которого не требуется дополнительный плагин:
(Это было взято из одного из моих внутренних плагинов, который может работать со старыми и новыми публикациями, таким образом... withType... stuff.
вместо:
project.plugins.withType(MavenPublishPlugin) {
project.publishsing {
publications {
myPub(MavenPublication) {
artifact myJar
}
}
}
}
сделайте следующее:
project.plugins.withType(MavenPublishPlugin) {
project.extensions.configure PublishingExtension, new ClosureBackedAction( {
publications {
myPub(MavenPublication) {
artifact myJar
}
}
})
}
Это не приведет к немедленному разрешению расширения, но будет применяться конфигурация в момент его первого разрешения кем-либо.
Конечно, было бы совершенно разумно использовать этот стиль конфигурации в вашем плагине для всего проекта, чтобы настроить репозитории и использовать расширение публикации в сценариях сборки, как обычно. Это позволило бы избежать путаницы для авторов buildscript.