How to publish to Artifactory with Gradle without publishing dependent projects - gradle

I'm updating some build.gradle files to add Artifactory publishing. In some cases I want to publish the top level project's artifacts without publishing artifacts for its dependent projects. The dependent projects get published on their own or when built by a different project.
I've added basic publishing and artifactory tasks to the build.gradle files and they work, but for example if there's a project called "api" that has a dependent project called "db", when I run the build.gradle for "api", it publishes the artifacts for both "api" and "db". I want it to only publish the api artifacts.
I'm not having much luck finding what I want on Jfrog's site. The documentation mentions "Use the artifactoryPublish.skip flag to deactivate analysis and publication", but honestly I don't know what to do with that and if it would help in my case.
The gradle scripts are referencing dependencies like this:
implementation project(path: ':db', configuration: 'default')
I've run the builds in both Eclipse and Jenkins. We use Gradle 7.4. I'm calling the clean, build, and artifactoryPublish tasks. I suspect there's probably an easy way to do this, and I'm just not seeing it.
For reference, this is my publishing task:
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}
And here's the publish part of the artifactory section:
publish {
repository {
repoKey = 'libs-release-local'
username = "${artifactory_user}"
password = "${artifactory_password}"
ivy {
ivyLayout = '[organization]/[module]/[revision]/ivy-[revision].xml'
artifactLayout = '[organization]/[module]/[revision]/[artifact]-[revision].[ext]'
mavenCompatible = true
}
}
defaults {
publications('mavenJava')
publishArtifacts = true
properties = ['qa.level': 'basic', 'dev.team' : 'core']
publishPom = true
publishIvy = true
}
}

I found an answer. For a project that has "db" as a dependency, after the dependencies section of my build.gradle file, I added the following:
gradle.startParameter.excludedTaskNames += "db:artifactoryPublish"
Now when I run the artifactoryPublish task for the api project, it does not execute for the db project, too.

For excluding the "db" project from publishing to Artifactory, you can add the following in your build.gradle file:
project('db') {
artifactoryPublish.skip = true
}

Related

Excluding one or two sub-projects from publication in gradle

I have a multi-project gradle build and I have applied the maven-publish plugin to all subprojects in my master build file.
I have also defined a default publication there called mavenJava.
This is all fine and now when I run ./gradlew artifactoryPublish I deploy artifacts from all the subprojects.
However, I would like to exclude two of my subprojects from publishing this mavenJava publication.
I've tried a bunch of things such as defining a boolean (skipDefaultPublish) in the ext block in the subprojects block in my master build file and including the publication definition inside a conditional if block and overwriting this variable in the ext block of the subprojects I do not want to publish it. That doesn't work and gradle complains that it Cannot configure the 'publishing' extension after it has been accessed..
I've tried other things but nothing seems to work.
The only thing that I know will work is defining the default publication block in all subprojects except for the ones that I do not want to publish from, but I have ~20 subprojects but only two that should not publish this type of artifact so this doesn't seem like the best thing to do.
So is there any way I can configure all subprojects to publish an artifact but override that in only two of the subprojects so that they don't do that?
UPDATE
To try to clarify what my project looks like.
root build.gradle
subprojects {
apply plugin: 'maven-publish'
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifactId = getCustomProjectId()
groupId = 'com.our.group.id'
}
}
}
apply plugin: "com.jfrog.artifactory"
artifactory {
contextUrl = ourContextUrl
publish {
repository {
repoKey = "ourRepoKey"
username = "ourArtifactoryUser"
password = "ourArtifactoryPass"
}
defaults {
publications('mavenJava')
publishArtifacts = true
publishPom = true
}
}
}
}
and in a subproject which should publish an artifact, just not the default one:
project(':exsub'){
publishing {
publications {
mavenSrc(MavenPublication) {
groupId "com.our.group.id"
artifactId "stuff-src"
artifact srcStuff
}
}
}
artifactoryPublish {
// publications.removeAll() //<- putting this here doesn't work
// publications.remove('mavenJava') //<- neither does this
publications ('mavenSrc') //<- this adds mavenSrc to the publication list but does not remove the mavenJava publication from it
}
}
There are several ways to publish artifacts, depending on used plugins.
To exclude particular module from publishing with modern (Gradle 4.x-7.x) publish like tasks:
tasks.withType(PublishToMavenRepository).configureEach { it.enabled = false }
Legacy uploadArchives:
uploadArchives.enabled = false
With com.jfrog.artifactory plugin:
artifactoryPublish.skip = true
Pheww... I think I finally figured out a way to do this (the aesthetics of the solution are quite debatable).
For me, it was sufficient to put a publishing.publications.remove(publishing.publications.mavenJava) line in the subproject.
However, I had to take care to put that line below the publishing{...} block in that subproject.
So now, the subprojects that should not publish the "default publication" look something like this:
project(':exsub'){
publishing {
publications {
mavenSrc(MavenPublication) {
groupId "com.our.group.id"
artifactId "stuff-src"
artifact srcStuff
}
}
}
// Remove the default publication (note: this must be located after the publishing block above)
publishing.publications.remove(publishing.publications.mavenJava)
artifactoryPublish {
publications ('mavenSrc') //<- this adds mavenSrc to the publication list but does not remove the mavenJava publication from it
}
}
Setting the following on subprojects you want to exclude worked for me:
project.tasks.publish.enabled = false
This does still require the maven-pulish plugin to be applied to the project, but no additional configuration is needed.
I found this setting here: https://discuss.gradle.org/t/disable-maven-publish-related-tasks-not-possible/13488
Let's consider the following multi-module project structure.
photos:
-> photo-client
-> photo-model
-> photo-service
In the above multimodule project, If I want to exclude the functionality of the photo-service submodule build jar (any distributive file(jar/war)) from uploading to the configured artifactory, then we have to use the below code snippet in the photo-service's build.gradle file
build.gradle
dependencies {
.....
}
project.afterEvaluate {
project.tasks.artifactoryPublish.enabled(false)
}
This question is specifically about what to do when some general configuration introduces one publication for all subprojects, but in one specific project you want to remove that "default" publication, but still have another publication. Most of the answers don't address this.
The answer by the original questioner does, but it didn't work for me.
This did:
tasks.withType(PublishToMavenRepository) {
onlyIf {
publication != publishing.publications.mavenJava
}
}
(where mavenJava is the name of the "default" publication to prevent).
This kind of solution is suggested by the Gradle documentation here: https://docs.gradle.org/current/userguide/publishing_customization.html#sec:publishing_maven:conditional_publishing

Setting up Artifactory in gradle global

currently I have a project which is deploying artifacts in our artifactory. For that Project everything is setted up perfect and it works.
I just wonderd if there is a possibility to set up the whole artifactory configuration global in gradle, so that I don't have to write the artifactory {...} stuff for each project.
You can maintain a file lets say build_dependency.gradle and define the task for all project
allprojects
{
//task common for all the project
}
subprojects
{
//task for subprojects
}
or specify the type of project e.g ext.warProject = 1 in dependency file and refer it in build_dependency.gradle as
if(project.hasProperty('warProject '))
{
//task here
}
and use this file in build.gradle like apply from: "$rootDir/path_to_file/build_dependency.gradle"
"$rootDir/path_to_dependenccy_file"`
You could simply write your own Gradle plugin that would be responsible for:
applying the artifactory plugin and other related plugin(s) like maven-publish
provide default values for the artifactory extension properties , like contextUrl, repoKey, credentials, etc...
Then your different projects will just have to apply your custom plugin, and provide only the project-specific configuration (configuration of the artefact to be published, for example, in publishing extension)
EDIT there are other ways to implement that, but it depends on what you mean by "global in gradle":
global to your own computer? then you could create a User InitScript that would contain the artifactory plugin configuration part
global to your team/company ? then you could need to implement a custom plugin, and maybe include this plugin into a custom gradle wrapper distribution (see example here
EDIT2 If you just want to set the artifactory plugin configuration of different sub-project of a same multi-project build, then the simpliest solution would be to define this configuration in the subprojects block of the root project build script:
subprojects {
apply plugin: "com.jfrog.artifactory"
artifactory {
publish {
contextUrl = '<repo url>'
repository {
repoKey = "<repo name>"
username = "user"
password = "pass"
}
}
}
}

Artifactory gradle and properties mutation by artifactoryPublish task DSL

My problem with build-info-extractor gralde plugin for artifactory
Source code with example for reproduce problem: https://github.com/lavcraft/gradle-artifactory-build-info-extractor-problems
Configure environment – artifactory_user artifactory_password artifactory_contextUrl
Run ./gradlew build aP
See jar artifacts properties in you artifactory instance
I expect, that this example (see below) works perfectly
artifactoryPublish {
properties = ['aa':'aaa']
properties {
nebula '**:**:**:*#*', 'not_added_prop':'sub0'
}
}
see sub0/build.gradle in github project
But it does not work. What is wrong with my example?
I think I found the cause of this issue.
Here's the artifactory closure configured in the build.gradle file, in the project you shared:
artifactory {
contextUrl = project.findProperty('artifactory_contextUrl')
publish {
repository {
repoKey = 'libs-snapshot-local'
username = project.findProperty('artifactory_user')
password = project.findProperty('artifactory_password')
}
defaults {
publications('nebula')
publishConfigs('archives')
publishIvy = false
properties {
nebula '*:*:*:*#*', 'want_to_add':'but not' // add only to *.pom artifacts. Why?
mavenJava commonProperties, '*:*:*:*#*'
}
}
}
}
As you can see above, the closure includes one publication (nebula) and one configuration (archives).
Running the build script as is prompts the following deployed artifacts:
$ gradle clean artifactoryPublish
Deploying artifact: http://localhost:8081/artifactory/libs-snapshot-local/ru/alfalab/platform/tests/sub0/0.1.1-SNAPSHOT/sub0-0.1.1-SNAPSHOT.jar
Deploying artifact: http://localhost:8081/artifactory/libs-snapshot-local/ru/alfalab/platform/tests/sub0/0.1.1-SNAPSHOT/sub0-0.1.1-SNAPSHOT.pom
Deploying artifact: http://localhost:8081/artifactory/libs-snapshot-local/ru/alfalab/platform/tests/sub1/0.1.1-SNAPSHOT/sub1-0.1.1-SNAPSHOT.jar
Deploying artifact: http://localhost:8081/artifactory/libs-snapshot-local/ru/alfalab/platform/tests/sub1/0.1.1-SNAPSHOT/sub1-0.1.1-SNAPSHOT.pom
Now, if you comment out the publication as follows:
//publications('nebula')
publishConfigs('archives')
You can the following:
Deploying artifact: http://localhost:8081/artifactory/libs-snapshot-local/ru/alfalab/platform/tests/sub0/0.1.1-SNAPSHOT/sub0-0.1.1-SNAPSHOT.jar
Deploying artifact: http://localhost:8081/artifactory/libs-snapshot-local/ru/alfalab/platform/tests/sub1/0.1.1-SNAPSHOT/sub1-0.1.1-SNAPSHOT.jar
So it looks like both the archives configuration and the nebula publication contribute the same two artifacts above.
Since "want_to_add" property is configured on the nebula publication (and not on the archives publication), the 2 jars contributed by the configuration don't get the property.
A simple fix for this is issue is to remove the archives configuration:
publications('nebula')
//publishConfigs('archives')
Alternatively, if for some reason you do want to have both the configuration and publication, you can add the property to your configuration as well. Here's how you do this:
properties = ['want_to_add': 'but not']
So the full closure, with both the publication, configuration and properties for both is this:
defaults {
publications('nebula')
publishConfigs('archives')
publishIvy = false
properties = ['want_to_add': 'but not']
properties {
nebula '*:*:*:*#*', 'want_to_add':'but not' // add only to *.pom artifacts. Why?
mavenJava commonProperties, '*:*:*:*#*'
}
}
You can read more about this here:
https://www.jfrog.com/confluence/display/RTF/Gradle+Artifactory+Plugin

Publish executable binary as Maven SNAPSHOT in Artifactory

Asking as a relative newbie to repo terminology and semantics:
I have a gradle project that builds a Spring-Boot jar file, and then runs an InstallAnywhere project file to package the jar as an installer for a Windows service. I need to publish the executable installer as a SNAPSHOT. I am using the gradle artifactory plugin (not the artifactory-publish plugin, only because I'm following the example of sister project).
The artifact is being published to the Maven snapshot repo, but the "-SNAPSHOT" placeholder is not being replaced by a timestamp. When I add the original Jar file to the artifacts to publish, the Jar file gets a timestamp added, but the .exe still does not. Relevant gradle code follows, and project version is set to "1.0.0-SNAPSHOT" in gradle.properties, along with other shown artifactory configuration properties:
task buildInstaller {
inputs.files cleanJarName.outputs
outputs.file installerFile
doLast {
project.exec {
workingDir 'InstallKit'
commandLine "${System.env.INSTALLANYWHERE_HOME}\\build.exe", 'MyInstallAnywhereProject.iap_xml', '-nupd'
}
}
}
artifactoryPublish {
dependsOn buildInstaller
}
configurations {
published
}
artifacts {
published installerFile
}
artifactory {
contextUrl = project.artifactoryContextUrl
publish {
repository {
repoKey = project.artifactoryPublishRepo
username = project.artifactoryUser
password = project.artifactoryPassword
}
defaults {
publishConfigs('published')
publishBuildInfo = true
publishArtifacts = true
publishPom = true
publishIvy = true
}
}
resolve {
repository {
repoKey = project.artifactoryResolveRepo
username = project.artifactoryUser
password = project.artifactoryPassword
maven=true
}
}
}
So why won't Artifactory properly snapshot an .exe? We were going to see if it was a limitation of Maven repos only handling Java-related types (jar, war, ear, etc.). So we looked at creating another Artifactory repo for binary snapshots using the generic(?) repo type, but the configuration screens do not offer the snapshot options present in the Maven repo configuration.
SNAPSHOT (actually Integration Revision) terminology is mandated by repository layouts.
Since Artifactory enforces single-typed repositories you are correct that a Maven repo will not handle the versioning of an .exe file.
Using a generic repo is the correct path to take - but you need to define your own folder and file integration revision to have Artifactory pick up on it.

Gradle: publish an artifact with a subset of files/dependencies of a project

I am lost in all these plugins :(
What I have so far, looks something like this:
artifactory {
contextUrl = artifactoryUrl
publish {
repository {
repoKey = project.repo
username = artifactoryUser
password = artifactoryPassword
maven = true
defaults {
publications('mavenJava')
}
}
}
version = "${majorVersion}${buildNumber}${snapshot}"
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifact sourceJar {
classifier = 'sources'
}
}
}
}
I am sorry, I did write this myself, but, mostly by copying and pasting things from various examples I found on the web, so I am not sure what this is actually doing :(
Surprisingly, this works: I can do gradle artifactoryPublish, and uploads a pom file and two jars (classes and sources) to artifactory.
But, I need to modify it, so that I can publish a subset of the project as a different artifact, and only include the dependencies that it requires.
I managed to build a jar file:
task utilJar(type: Jar) {
from sourceSets.main.output.classesDir
include '**/util/*.class'
baseName 'basic-util'
}
I also defined a Configuration with a subset of dependencies:
configurations {
util
}
dependencies {
util "org.apache.commons:commons-lang3:3.4"
util "com.google.guava:guava:18.0"
}
artifacts {
util utilJar
}
This is where I get stuck. How do I get this new artifact published?
I tried following the same strategy:
publishing {
publications {
mavenUtil(MavenPublication) {
from components.java
artifact utilJar {
classifier = 'util'
}
}
}
}
artifactory {
defaults {
publications('mavenUtil')
}
}
(this is in a subproject, so I need it do be incremental)
This does not work:
Could not find method defaults() for arguments [build_8axxghkylu3559p5lal6spy1u$_run_closure7$_closure11#38abcbd4]
But, even if it did, it would still be not be quite what I need, because I don't know how I could then publish a particular artifact: the only way I could ever publish anything at all is gradle artifactoryPublish, but that does not ask me which artifacts to publish. Will it publish everything every time?
As you can see, I am hopelessly lost here :(
Could someone with a clue please show me the light?
UPDATE So, I removed the last artifactory closure from the build, and now I not getting the error, but still can't get it to do what I need.
My artifactory seems to be not in good mood right now, so I am publishing locally.
gradle publishToMavenLocal creates a single artifact as before, but adds my new "-util" jar to it. This is not at all what I want. I need a new, separate artifact, with that jar file, and its own set of dependencies.
Here: https://docs.gradle.org/current/userguide/publishing_maven.html#publishing_maven:repositories I found a suggestion, that "The created task is named “publish«PUBNAME»PublicationTo«REPONAME»Repository”". This does not seem to to be true, because gradle publishUtilMavenPublicationToMavenLocalRepository (with all the case variations I could think off) says that there is no such task. :(
Have you tried using the set me up feature? It available for all version of Artifactory. It should provide a good starting point to configure you gradle project to work with Artifactory.
Specifically for Gradle it can assist you with generating the relevant configuration according to the repositories you wish to resolve / publish from / to, defining the relevant dependencies to install the jfrog plugin etc.

Resources