jfrog / artifactory-gradle-plugin

JFrog Gradle plugin for Build Info extraction and Artifactory publishing.
Apache License 2.0
20 stars 14 forks source link

Error on artifactory plugin when applying artifactory separately on subprojects of multi-module project #74

Open TheBatOutOfHell opened 9 months ago

TheBatOutOfHell commented 9 months ago

How can we help?

I am not sure whether this is an artifactory issue or I am doing something wrong. Hope to clarify this.

TLDR In a multi-module project should it be possible to apply a plugin separately to each subproject like

./app/webapp/build.gradle
plugins {
    id "war"
    id "com.jfrog.artifactory" version "5.1.10"
}
dependencies {
    implementation project(':library')
}

./app/library/build.gradle
plugins {
    id "java"
    id "com.jfrog.artifactory" version "5.1.10"
}

./app/settings.gradle
rootProject.name = 'app'
include 'webapp'
include 'library'

or is it necessary to predefine it in the root project with apply true|false? Because applying artifactory separately on each subproject without predefining it in root-project seems to work but applying additional plugin on one subproject yields

An exception occurred applying plugin request [id: 'com.jfrog.artifactory', version: '5.1.10']
> Failed to apply plugin class 'org.jfrog.gradle.plugin.artifactory.ArtifactoryPlugin'.
   > Cannot add extension with name 'artifactory', as there is an extension already registered with that name.

IN DETAIL Initially I encountered this situation when applying custum plugins in a multi-module java project and adding one other dependency (which was not used in the custom plugins) on only one of the subprojects.

For easier reproduction I have created a small project without custom plugins like this:

rootproject
- lib-project
  build.gradle
- webapp-project
  build.gradle
settings.gradle

Usually when creating such a project with gradle init it is basically this result. So there is a settings.gradle in root (no build.gradle) and build.gradle files in the modules. I understand from different discussions in gradle forums that it is usually not good practice to have a build.gradle in root project.

So avoiding build.gradle in root project I have this in modules build.gradle

./webapp/build.gradle
plugins {
    id "war"
    id "com.jfrog.artifactory" version "5.1.10"
}

./lib/build.gradle
plugins {
    id "java"
    id "com.jfrog.artifactory" version "5.1.10"
}

Everything seems to be ok, it is building. But I wonder whether it is right to do so or if there should definitely be some single point of entry like e.g. root build.gradle with something like

plugins {
    id "com.jfrog.artifactory" version "5.1.10" apply false
}

and eventually omitting the version in the modules build.gradle files.

Reason why I am asking is that doing it like shown in above example applying it separately in each subproject yields an error as soon as I add an additional other plugin to only one of the subprojects.

So something like

./webapp/build.gradle
plugins {
    id "war"
    id "com.liferay.source.formatter" version "5.2.58"
    id "com.jfrog.artifactory" version "5.1.10"
}

./lib/build.gradle
plugins {
    id "java"
    id "com.jfrog.artifactory" version "5.1.10"
}

issues

An exception occurred applying plugin request [id: 'com.jfrog.artifactory', version: '5.1.10']
> Failed to apply plugin class 'org.jfrog.gradle.plugin.artifactory.ArtifactoryPlugin'.
   > Cannot add extension with name 'artifactory', as there is an extension already registered with that name.

during build/refresh/etc. processes.

In contrast when adding the additional plugin to both subprojects build is working again.

./webapp/build.gradle
plugins {
    id "war"
    id "com.liferay.source.formatter" version "5.2.58"
    id "com.jfrog.artifactory" version "5.1.10"
}

./lib/build.gradle
plugins {
    id "java"
    id "com.liferay.source.formatter" version "5.2.58"
    id "com.jfrog.artifactory" version "5.1.10"
}

This one builds. Also predefining artifactory in root build.gradle with apply false seems to solve the problem.

Reason for asking is that I am using some own convention plugins, say

./main/src/groovy/common-conventions.gradle
plugins {
  id "at.bxm.svntools" version "3.1"
  id "com.jfrog.artifactory" version "5.1.10"
}

./main/src/groovy/web-conventions.gradle
plugins {
  id "war"
  id "common-conventions"
}

./main/src/groovy/lib-conventions.gradle
plugins {
  id "java"
  id "common-conventions"

Basically using this plugin in my project works and artifactory is available. And for sure I want to use web-conventions on web-project and lib-conventions on lib-project so there is nothing preapplied or so in root. But doing this issues the same error as soon as I add additional library directly to my projects.

E.g.

./webapp/build.gradle
plugins {
    id "com.liferay.source.formatter" version "5.2.58"
    id "web-conventions" version "1.0"
}

./lib/build.gradle
plugins {
    id "lib-conventions" version "1.0"
}

also yields

An exception occurred applying plugin request [id: 'com.jfrog.artifactory', version: '5.1.10']
> Failed to apply plugin class 'org.jfrog.gradle.plugin.artifactory.ArtifactoryPlugin'.
   > Cannot add extension with name 'artifactory', as there is an extension already registered with that name.

As I honestly do not fully understand what is going on I created the simple reproducer without any convention plugins included only using artifactory plugin and some other random plugin. Tested this on the simple project with one or two other random plugins (instead of com.liferay.source.formatter) and I see the same error again.

So I wonder if I am wrong in the way the plugins are applied here then I would have to rethink the custom plugins again or if this is indeed an issue with artifactory or the way artifactory plugin is working.

If artifactory plugin requires to be preconfigured in root project then I wonder how I can do this and still use my plugins then?

And I am curious, concerning the approach to apply plugin separately on each subproject:

./webapp/build.gradle
plugins {
    id "war"
    id "com.jfrog.artifactory" version "5.1.10"
}

./lib/build.gradle
plugins {
    id "java"
    id "com.jfrog.artifactory" version "5.1.10"
}

Is this a "valid" way to apply a plugin or is it necessary to have the plugin preconfigured in some root plugins section? To maintain the version I am also using a published version-catalog and I would simply use alias(libs.plugins.jfrog.artifactory) on all the subprojects that need the plugin without even bothering to declare it in root somehow.

Thx. Rob

TheBatOutOfHell commented 9 months ago

Ok. I learned now that this indeed seems to be an issue with artifactory and the fact that it is silently auto-applying to root. So guess I will have to work with that situation.

pernilla commented 7 months ago

Did you find a solution for this? Moving it in to the root project for me doesn't even compile? Looking at the sample https://github.com/jfrog/artifactory-gradle-plugin/blob/main/src/functionalTest/resources/gradle-kts-example-publish/build.gradle.kts Intellij can't even resolve the imports of jfrog when put in the root folder.

TheBatOutOfHell commented 7 months ago

A solution for what exactly? What are the issues you have?

In my case after quite some discussions in gradle board the solution with artifactory usage in multi module project was basically

applying it to root with version and if not needed in root with apply false (groovy syntax in my case, but guess it should work with similar with kotlin):

plugins {
    id "com.jfrog.artifactory" version "5.1.10" apply false
}

and in subprojects, that need artifactory do

plugins {
    id "com.jfrog.artifactory"
}

You can find discussion here in gradle board

maksym-moroz commented 5 months ago

@TheBatOutOfHell, there is a way to extract the common configuration into a convention plugin, I described my solution here. This allows you to avoid duplicate logic in your subproject.

TheBatOutOfHell commented 5 months ago

@maksym-moroz Thank you. I have implementend a convention plugin already as you might find out under the link in my comment of Nov. 22, 2023. However there will still be some things to consider especially when the project is configured as multi-module project.

stroeter commented 1 week ago

It seems to me that you can apply the plugin to all projects or just one of a multi-module gradle project because of the registration for the buildinformation. I guess this is a bug that should be fixed. Would be fine to apply the artifactory gradle plugin to any number of modules of a gradle multi-module project.