Context URL cannot be empty - Artifactory Gradle Plugin - gradle

I'm trying to get to the Artifactory Gradle plugin working to publish to my local Artifactory instance.
I have the latest version (default install) running at localhost:8081/artifactory. I can verify this with access via a webbrowser.
However, with my bare minimum example .. I am getting a "Context URL cannot be found error
Note that I have specified all the mandatory required Artifactory configurations settings - (as indicated on the Artifactory Gradle WebPage) .. including the Context URL.
buildscript {
repositories{ maven { url 'http://repo.jfrog.org/artifactory/gradle-plugins' } }
dependencies{ classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:2.0.12'}
}
apply plugin: 'artifactory'
artifactory {
contextUrl = 'http://localhost:8081/artifactory' //The base Artifactory URL if not overridden by the publisher/resolver
publish {
repository {
repoKey = 'integration-libs' //The Artifactory repository key to publish to
username = 'admin' //The publisher user name
password = 'password'
}
}
resolve {
repository {
repoKey = 'libs-releases' //The Artifactory (preferably virtual) repository key to resolve from
}
}
}

This looks like a weird bug and I'm not sure what causes it. I get it in some of my gradle build files but others seem to work fine.
I fixed it by defining the contextUrl again inside the publish element, so your script will now look like:
artifactory {
contextUrl = 'http://localhost:8081/artifactory' //The base Artifactory URL if not overridden by the publisher/resolver
publish {
contextUrl = 'http://localhost:8081/artifactory' // <- this is the fix
repository {
repoKey = 'integration-libs' //The Artifactory repository key to publish to
username = 'admin' //The publisher user name
password = 'password'
}
}
resolve {
repository {
repoKey = 'libs-releases' //The Artifactory (preferably virtual) repository key to resolve from
}
}
}
You might also have to define it again inside the resolve element.

Related

gradle can't resolve dependency in privare repository (nexus)

I am running into problems with gradle while resolving dependencies. Some of my projects uses a core-lib which I provide by my private repository - nexus3. And the weirdest part is, one of this projects resolves the dependency, while the others can't. I have no Idea what I am doing wrong:
This is how I define my gradle repositories:
repositories {
maven {
credentials {
username = "user"
password = "password"
}
url = uri("https://my-nexus-url/repository/group-repo/")
}
mavenCentral()
}
This is how the dependency is implemented:
dependencies {
...
implementation("my.lib.core:core:1.0")
...
}
This is how is the puiblishing configure block:
publishing {
publications {
create<MavenPublication>("maven") {
groupId = "my.lib.core"
artifactId = "core"
version = "1.0"
from(components["java"])
}
}
repositories {
maven {
credentials {
username = "user"
password = "password"
}
url = uri("https://my-nexus-url/repository/release-repo/")
}
}
}
I am also able to download the artifact via nexus web ui and curl. Furthermore already one of these projects is able to implement it. The rest of them throws:
Could not resolve my.lib.core:core:1.0.
Required by:
project :lib
Possible solution:
- Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/userguide/declaring_repositories.html
Running gradlew ass --refresh-dependencies works fine and ends with:
Cached resource https://my-nexus-url/repository/group-repo/my/lib/core/core/1.0/core-1.0.jar is up-to-date (lastModified: Tue Mar 08 23:05:19 CET 2022).

Unable to publish jar to Gitlab package registry with gradle

I am trying to publish some jar artefacts on gitlab package registry but I get this error from the server :
Received status code 415 from server: Unsupported Media Type
Here is the publishing section of my build.gradle.kts :
publishing {
publications {
create<MavenPublication>("maven"){
artifact(tasks["bootJar"])
}
}
repositories {
maven {
url = uri("https://gitlab.com/api/v4/groups/my-group/-/packages/maven")
name = "Gitlab"
credentials(HttpHeaderCredentials::class) {
name = "Token"
value = System.getenv("CI_JOB_TOKEN")
}
authentication {
create<HttpHeaderAuthentication>("header")
}
}
}
}
In my gitlab-ci, I added a task for publish the artefacts :
deploy:
stage: deploy
script: gradle publish
only:
- master
Any help would be appreciated
Quick answer
Replace your publishing url pointing to the group-scope with the one pointing to the specific-package-repository, e.g. on gitlab.com:
https://gitlab.com/api/v4/projects/<your-project-id>/packages/maven
You need to replace <your-project-id> with your specific project-id of course.
Related to this a quote from docs.gitlab:
Note: In all cases, you need a project specific URL for uploading a package in the distributionManagement section.
Or in other words: Only the general repositories section can use your groups-url for searching other already published artifacts! (I also had to understand that). So:
you cannot publish to the group-package-store on gitlab, you can just search there.
Publication goes always to the project-specific package-store, which will then be visible at group-scope too.
Example gradle config (kotlin-dsl)
repositories {
mavenCenter()
jcenter()
// Here you USE the group api/v4 url for SEARCHING packages
maven {
name = "GitLab"
url = uri("https://gitlab.com/api/v4/groups/my-group/-/packages/maven")
credentials(HttpHeaderCredentials::class) {
name = "Job-Token"
value = System.getenv("CI_JOB_TOKEN")
}
authentication {
create<HttpHeaderAuthentication>("header")
}
}
}
publishing {
publications {
create<MavenPublication>("maven"){
artifact(tasks["bootJar"])
}
}
repositories {
maven {
// here your PROVIDE the PROJECT-URI for publishing your package
// in the project-specific package-space which is also visible at
// the group scope above
url = uri("https://gitlab.com/api/v4/projects/<your-project-id>/packages/maven")
name = "Gitlab"
credentials(HttpHeaderCredentials::class) {
name = "Job-Token"
value = System.getenv("CI_JOB_TOKEN")
}
authentication {
create<HttpHeaderAuthentication>("header")
}
}
}
}
More Info
There are multiple scenarios on how you may interact with the maven-repository-space on GitLab. The three switches are:
The place where you want to look for existing published packages
project-scope (https://.../api/v4/projects/<project-id>/packages/maven)
group-scope (https://.../api/v4/groups/<group-id>/-/packages/maven)
instance-scope (https://.../api/v4/packages/maven)
The authorization-method you want to use
PERSONAL_ACCESS_TOKEN
DEPLOY_TOKEN
CI_JOB_TOKEN
The place where your want to publish your package
this must always be a specific project-url (https://.../api/v4/projects/<project-id>/packages/maven)
I think the most important thing is to make sure you've enabled archives in your project:
Go to Project Settings
Expand Permissions
Switch on "Packages"
Apparently, there are also other reasons for the response status 415 Unsupported Media Type:
I ran into the same error message while trying to publish to the project repository. The error that I made was to use the URL-encoded path of the project instead of the project ID in the repository URL.
From the Gitlab documentation (emphasis added):
For retrieving artifacts, use either the URL-encoded path of the project
(like group%2Fproject) or the project's ID (like 42). However, only the
project's ID can be used for publishing.
This is the build.gradle.kts configuration that worked for me on my self-hosted Gitlab instance for publishing a Spring Boot fat JAR:
plugins {
/* ... other stuff ... */
`java-library`
`maven-publish`
}
publishing {
publications {
create<MavenPublication>("bootJava") {
artifact(tasks.getByName("bootJar"))
}
}
repositories {
maven {
val projectId = System.getenv("CI_PROJECT_ID")
name = "Project Name"
url = uri("https://gitlab.example.com/api/v4/projects/${projectId}/packages/maven")
credentials(HttpHeaderCredentials::class) {
name = "Job-Token"
value = System.getenv("CI_JOB_TOKEN")
}
authentication {
create<HttpHeaderAuthentication>("header")
}
}
}
}

Publish Snapshot to oss.jfrog.org with multiple modules fails with 403

I'm trying to publish a project with multiple modules to artifactory (oss.jfrog.org). When I run artifactoryPublish I get a 403 error but I know it's not a permissions issue because it works with a single module. It only fails trying publish multiple modules.
Some modules are aars and others are jars and all include sources. I can publish them all to Bintray, but can't publish to artifactory (for snapshots).
So the question is, how do I configure a multi-module project to publish snapshots to oss.jfrog.org.
I've figured out that if I change it to publish a single module and make the artifact name the same as the last part of the group, it works, but a different name doesn't work (gives 403 error).
So if group is com.example.foo I can publish foo.jar (com/example/foo/foo/1.0.0-SNAPSHOT/foo-1.0.0.jar). But I can't publish bar.jar (com/example/foo/bar/1.0.0-SNAPSHOT/bar.jar).
This gradle is included in every project's build.gradle
afterEvaluate {
publishing {
publications {
mavenPublication(MavenPublication) {
artifact sourcesJar
if (project.plugins.hasPlugin("com.android.library")) {
artifact("$buildDir/outputs/aar/${project.name}-debug.aar")
} else {
artifact("$buildDir/libs/${project.name}-${version}.jar")
}
groupId "com.example.foo"
artifactId project.name // changing this to "foo" works for a single project
version version
pom {
name.set(project.name)
url.set(POM_URL)
packaging POM_PACKAGING
version version
licenses {
license {
name.set(POM_LICENSE_NAME)
url.set(POM_LICENSE_URL)
}
}
developers {
developer {
name.set(POM_DEVELOPER)
}
}
scm {
url.set(POM_SCM_URL)
connection.set(POM_SCM_CONNECTION)
developerConnection.set(POM_SCM_DEV_CONNECTION)
}
}
}
}
}
bintray {
user = project.findProperty('bintrayUser') ?: System.getenv('BINTRAY_USER')
key = project.findProperty('bintrayApiKey') ?: System.getenv('BINTRAY_API_KEY')
configurations = ['archives']
publish = true
dryRun = true
pkg {
name = project.name
repo = BINTRAY_REPO
userOrg = BINTRAY_ORG
licenses = [POM_LICENSE_NAME]
vcsUrl = POM_SCM_URL
version {
name = project.name
released = new Date()
}
}
}
artifactory {
contextUrl = 'http://oss.jfrog.org'
publish {
repository {
repoKey = 'oss-snapshot-local'
username = project.findProperty('bintrayUser') ?: System.getenv('BINTRAY_USER')
password = project.findProperty('bintrayApiKey') ?: System.getenv('BINTRAY_API_KEY')
}
defaults {
publications('mavenPublication')
publishArtifacts = true
publishPom = true
}
}
resolve {
repoKey = 'jcenter'
}
}
}
Artifactory returns a 403 whenever you're trying to publish an artefact that already exists. In your case, if you've previously published snapshot artefacts from your multi module build, whenever you will try doing that again, you will get a 403. I know you can configure the user access to provide delete permissions to the account you are using to deploy, as indicated here. However, overwriting history is not considered a good practice.
Regarding renaming your groups and artefacts, I don't think that will provide a solution, as it's not your GAV coordinates that are the issue, but rather the fact that artefacts with matching GAV already exist.
If I may ask, why do you want to use SNAPSHOT artefacts? Can you not achieve the same behaviour with dynamic dependencies and dependency locking?

Publishing Maven artifact to artifactory with different artifact ID

New to Maven Publishing. Our team has started using Artifactory and I'm trying to figure out how to publish to it, but using a custom artifact ID. Here's the relevant part of my build.gradle file
def applicationName = 'example-api'
def applicationVersion = '1.0.0.1'
def group = 'com.example.api'
def archiveName = "${applicationName}##${applicationVersion}"
bootWar {
archiveFileName = "${archiveName}.war"
}
publishing {
publications {
mavenJava(MavenPublication) {
artifact(file("build/libs/${archiveName}.war"))
afterEvaluate {
artifactId archiveName
groupId group
version applicationVersion
}
}
}
}
artifactory {
contextUrl = "http://172.17.0.2:32447/artifactory"
publish {
repository {
repoKey = 'libs-release-local'
username = 'admin'
password = 'password1'
maven = true
}
defaults {
publications('mavenJava')
publishBuildInfo = true
publishArtifacts = true
publishPom = false
}
}
clientConfig.info.setBuildName(applicationName)
clientConfig.info.setBuildNumber(applicationVersion)
}
But it seems it's never keeps the same name as the WAR file that's produced in the build. This is the closest I've gotten:
Ideally, I'd like to have the artifact be called just 'example-api##1.0.0.1.war' since it will be deployed to Tomcat.
When I try to remove groupId, Artfactory seems unable to create a repo URL, and if I omit the the version, the artifact name is then example-api##1.0.0.1-unspecified.war
Any thoughts?
What you see is the expected behaviour.
Maven artifact names are strictly <artifactId>-<version>.<extension>.
So when you set the publication configuration as follows:
artifactId = example-api##1.0.0.1
version = 1.0.0.1
extension = war
It results in an artifact named example-api##1.0.0.1-1.0.0.1.war
I would strongly recommend dropping the version from the artifactId part, to be better aligned with Maven conventions.
An alternative would be to use an Ivy repository, which has more flexibility around specifying the artifact name.

Publish wrapped OSGi bundles to artifactory with Gradle

As not all jars are automatically usable OSGi bundles I use wrapping to generate them. After having being wrapped I'd like to publish them to my Artifactory repository. However, my lack of understanding of Gradle inhibits success, and after reading several suggested Stackoverflow answers I am still stuck.
This is my build.gradle file:
buildscript {
repositories {
maven { url 'http://localhost:8081/artifactory/gradle-dev' }
}
dependencies {
classpath 'org.standardout:bnd-platform:1.2.0'
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4+"
}
}
apply plugin: 'org.standardout.bnd-platform'
apply plugin: "com.jfrog.artifactory"
apply plugin: 'maven-publish'
group = 'com.google.code.gson'
version = '2.8.0'
publishing {
publications {
osgiBundles(MavenPublication) {
artifacts {
files("build/plugins")
}
}
}
}
artifactory {
contextUrl = "${artifactory_contextUrl}" //The base Artifactory URL if not overridden by the publisher/resolver
publish {
repository {
repoKey = 'gradle-dev-local'
username = "${artifactory_user}"
password = "${artifactory_password}"
maven = true
}
defaults {
publications ('osgiBundles')
}
}
resolve {
repository {
repoKey = 'gradle-dev'
username = "${artifactory_user}"
password = "${artifactory_password}"
maven = true
}
}
}
platform {
useBndHashQualifiers = false
defaultQualifier = ''
bundle(group: 'com.google.code.gson', name:'gson', version:'2.8.0') {
bnd {
instruction 'Export-Package', 'com.google.gson,com.google.gson.stream,com.google.gson.annotations,com.google.gson.reflect'
}
}
}
The output of the script is as follows:
gradle artifactoryPublish
:generatePomFileForOsgiBundlesPublication
:artifactoryPublish
Deploying artifact: http://localhost:8081/artifactory/gradle-dev-local/com/google/code/gson/bundle-jars/2.8.0/bundle-jars-2.8.0.pom
Deploying build descriptor to: http://localhost:8081/artifactory/api/build
Build successfully deployed. Browse it in Artifactory under http://localhost:8081/artifactory/webapp/builds/bundle-jars/1489323863518
When I look in the artifactory repository the structure is not what I expected:
+- com
+--- google/code/gson/bundle-jars
|+-- 2.8.0
| +- bundle-jars.pom
+--- maven-metadata.xml
The wrong directory structure (google/code/gson/bundle-jars), where I expected several sub directorties (google, code, gson) with a 2.8.0 and a jar file.
I think I have to change the publications block, but I don't know what it should be.
I use unpuzzle (or rather this fork) to create Maven artifacts from OSGi bundles (and publish them to Artifactory).
This is probably not the most efficient solution for your use case, but at least something that works and I can come up with fast.
Here is an example of where I use unpuzzle for this purpose. Maybe that can serve as a starting point (together with the unpuzzle docs). There is a lot of bloat in my example because there I try to actually determine the original Maven artifacts for OSGi bundles created from them - as you always want the OSGi bundle, that's probably not relevant for you.
Note that by default the published artifacts will have different names (based on the bundle symbolic name) and a different group (which is configurable). But I think that is to be preferred over having the original group and name, otherwise it may get confused w/ the original. Adapting the group and name individually is possible as you can see in the example.
The publication should be as follows:
publishing {
publications {
osgiBundles(MavenPublication) {
groupId 'my.group'
artifactId 'com.google.code.gson'
version '2.8.0'
artifact file("build/plugins/com.google.code.gson_2.8.0.jar")
}
}
}

Resources