Unable to publish jar to Gitlab package registry with gradle - 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")
}
}
}
}

Related

Configure description for package published to the GitHub Packages Gradle registry

When publishing a package to the GitHub Packages Gradle registry, the resulting package's description is empty.
Is it possible to set the package description via config?
I have the following (abridged) configuration in build.gradle.kts, I was assuming it would use pom.description or the repo's README.md as the description but that doesn't seem to be the case.
plugins {
`maven-publish`
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
groupId = project.group.toString()
artifactId = rootProject.name
version = project.version.toString()
from(components["java"])
pom {
name.set("steam-webapi-kt")
description.set("Steam WebAPI wrapper in Kotlin and Ktor")
url.set("https://github.com/j4ckofalltrades/steam-webapi-kt")
}
}
}
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/j4ckofalltrades/steam-webapi-kt")
credentials {
username = System.getenv("GITHUB_ACTOR")
password = System.getenv("GITHUB_TOKEN")
}
}
}
}
Sample package: https://github.com/j4ckofalltrades/steam-webapi-kt/packages/899640

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?

how to write project information in gradle?

I am converting a sample maven project to Gradle. In the maven project, there are tags like licenses, organization, developers. I just want to give these details in Gradle project. I have tried to add the following in build.gradle file,
licenses {
license {
name = 'Apache 1'
url = 'http://www.apache.org/licenses/LICENSE-1.0.txt'
distribution = 'repo'
comments = 'OSS license'
}
}
organization {
name = 'Sonatype'
url = 'http://www.sonatype.com'
}
but it gives an error.
> Could not find method licenses() for arguments [build_aa7z0myalt7c30hobty4ylab$_run_closure1#227a2f2] on root project 'simple-weather' of type org.gradle.api.Project.
How to do the same, Whether I have to add some plugin?
Customizing the POM published to Maven repositories is up to the maven-publish plugin.
Example:
plugins {
id 'maven-publish'
}
publishing {
publications {
mavenJava(MavenPublication) {
pom {
licenses {
license {
name = 'Apache 1'
url = 'http://www.apache.org/licenses/LICENSE-1.0.txt'
distribution = 'repo'
comments = 'OSS license'
}
}
organization {
name = 'Sonatype'
url = 'http://www.sonatype.com'
}
}
}
}
}

How do I replace a Maven repository with a local directory after it is defined in a Gradle build?

I'm trying to write tests for a build process, so my unit test wants to replace the actual repository locations with local locations to avoid poisoning the real server. (Plus, I suppose, the person running the test might not have access to publish anyway.)
In the build itself:
publishing {
repositories {
maven {
name = 'snapshot'
url = "${artifactory_contextUrl}/libs-snapshot-local"
credentials {
username artifactory_user
password artifactory_password
}
}
maven {
name = 'release'
url = "${artifactory_contextUrl}/libs-release-local"
credentials {
username artifactory_user
password artifactory_password
}
}
}
}
In my test build, I'm trying to override it with this:
publishing {
repositories {
getByName('snapshot') {
url = uri('/tmp/local-repo/snapshots')
}
getByName('release') {
url = uri('/tmp/local-repo/release')
}
}
}
When I try to run the build, I get:
Execution failed for task ':publishMavenJavaPublicationToReleaseRepository'.
> Failed to publish publication 'mavenJava' to repository 'release'
> Authentication scheme 'all'(Authentication) is not supported by protocol 'file'
There are a lot of posts out on the web about this specific error, but it always seems to be people who accidentally put a file path in when they should have put a URI. I'm putting in a URI deliberately, though, so is there a way to get this to work?
I have also tried this:
publishing {
repositories {
clear()
maven {
name = 'snapshot'
url = uri('/tmp/local-repo/snapshots')
}
maven {
name = 'release'
url = uri('/tmp/local-repo/release')
}
}
}
That fails with:
A problem occurred configuring root project 'test-common-plugin1913987501683151177'.
> Exception thrown while executing model rule: PublishingPluginRules#publishing(ExtensionContainer)
> Cannot add task 'publishMavenJavaPublicationToSnapshotRepository' as a task with that name already exists.
I was surprised that deleting all the repositories doesn't also delete all the tasks they own. When I try to programmatically delete the task it's complaining about, Gradle claims that it doesn't exist.
Alright, I ended up having to read the source of Gradle (again), but I found a way to do it. Essentially you can directly set credentials back to null, like this:
publishing {
repositories {
getByName('snapshot') {
url = uri('/tmp/local-repo/snapshots')
configuredCredentials = null
}
getByName('release') {
url = uri('/tmp/local-repo/release')
configuredCredentials = null
}
}
}

Context URL cannot be empty - Artifactory Gradle Plugin

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.

Resources