Proper credentials for gradle publish at gitlab CI/CD

:hugs: Please help fill in this template with all the details to help others help you more efficiently. Use formatting blocks for code, config, logs and ensure to remove sensitive data.

Problem to solve

gradle publish task failing with

FAILURE: Build failed with an exception.

* What went wrong:

Execution failed for task ‘:publishMavenPublicationToMavenRepository’.

> Failed to publish publication ‘maven’ to repository ‘maven’

Could not PUT ‘https://gitlab.com/api/v4/projects/34294364/packages/maven/jpsgcs/jpsgcs/3.3.4-2/jpsgcs-3.3.4-2.jar’. Received status code 403 from server: Forbidden

* Try:

> Run with --stacktrace option to get the stack trace.

> Run with --info or --debug option to get more log output.

> Run with --scan to get full insights.

> Get more help at https://help.gradle.org.

I cannot find any mention of 403 Error via the search tool

My publish task is defined as

publishing {
  publications {
    maven(MavenPublication) {
      group = 'jpsgcs'
      artifactId = 'jpsgcs'
      version = project.version
      from components.java
    }
  }
  repositories {
    maven {
      url = "https://gitlab.com/api/v4/projects/34294364/packages/maven"
      credentials {
	      username = "gitlab-ci-token"
	      password = System.getenv("CI_JOB_TOKEN")
      }
    }
  }
}


Configuration

The build is successful, but the publish fails with a 403 error.

default:

image: gradle:8.9-jdk21

# Disable the Gradle daemon for Continuous Integration servers as correctness

# is usually a priority over speed in CI environments. Using a fresh

# runtime for each build is more reliable since the runtime is completely

# isolated from any previous builds.

variables:

GRADLE_OPTS: “-Dorg.gradle.daemon=false”

CI_DEBUG_SERVICES: trace

stages:

  • release

  • deploy

before_script:

  • export GRADLE_USER_HOME=`pwd`/.gradle

  • echo "find properties in " $GRADLE_USER_HOME

  • echo “job token:” + $CI_JOB_TOKEN

release:

stage: release

script:

- gradle --build-cache -PgitLabPrivateToken=$CI_JOB_TOKEN assemble

- echo "Building in " $(pwd)

cache:

key: "$CI_COMMIT_REF_NAME"

policy: push

paths:

  - build

  - .gradle

artifacts:

paths:

  - build/libs/\*

expire_in: 1 week

deploy:

stage: deploy

script:

- echo "getting pushy"

- 'gradle publish'

Versions

Please select whether options apply, and add the version information.

  • Self-managed
  • xc GitLab.com SaaS
  • Dedicated
  • Self-hosted Runners

Versions

  • GitLab

Never mind

Sorry for the noise

https://gitlab.com oh my

OK, I give up. What is the proper/typical/canonical url (the part BEFORE “/api/v4/projects//packages/maven ? What “name” or what “service” is expected?

There’s a good example here: Maven API | GitLab Docs which shows a curl command with the full url.

From your initial post you have url = "https://gitlab.com/api/v4/projects/34294364/packages/maven" as the url, but in the documentation it also shows additional information being passed after the maven part of the url. If you are using gitlab.com, then the part before api is correct. It would suggest that the remainder of the url is incorrect, or perhaps your token to push doesn’t have the appropriate permissions to push to the package repository.

Check and verify your url with the documentation linked, as well as ensure your token has the correct privileges.

Thanks.

I did revert to “gitlab.com” - couldn’t think of what else it could be. The remainder of the url as generated by gradle is group/artifact/version/jar which I believe is correct. On my latest attempt I got a 401 “Unauthorized” so my deploy token must need some work.

Cheers

1 Like

Is this correct as far as the gradle build file is concerned?

publishing {
  publications {
    library(MavenPublication) {
      group = 'jpsgcs'
      artifactId = 'jpsgcs'
      version = project.version
      from components.java
    }
  }
  repositories {
    maven {
      url = "https://gitlab.com/api/v4/projects/34294364/packages/maven"
      name  = "jpsgcs"
      credentials(HttpHeaderCredentials) {
	      name = System.getenv("CI_DEPLOY_USER")
	      value = System.getenv("CI_DEPLOY_PASSWORD")
      }
      authentication {
	      header(HttpHeaderAuthentication)
      }
    }
  }
}

The token has most privs including package repository write, which is the part which is failing with 401 (i.e. "PUT <jar url>")

Here’s the gradle –debug output reduced to relevant portion.

[DEBUG] [org.apache.http.impl.execchain.MainClientExec] Executing request PUT /api/v4/projects/34294364/packages/maven/jpsgcs/jpsgcs/3.3.4-2/jpsgcs-3.3.4-2.jar HTTP/1.1
[DEBUG] [org.apache.http.impl.execchain.MainClientExec] Target auth state: UNCHALLENGED
[DEBUG] [org.apache.http.impl.execchain.MainClientExec] Proxy auth state: UNCHALLENGED
[DEBUG] [org.apache.http.impl.execchain.MainClientExec] Connection can be kept alive indefinitely
[DEBUG] [org.apache.http.impl.auth.HttpAuthenticator] Authentication required
[DEBUG] [org.apache.http.impl.auth.HttpAuthenticator] gitlab.com:443 requested authentication
[DEBUG] [org.apache.http.impl.client.TargetAuthenticationStrategy] Authentication schemes in the order of preference: [Negotiate, Kerberos, NTLM, CredSSP, Digest, Basic]
[DEBUG] [org.apache.http.impl.client.TargetAuthenticationStrategy] Challenge for Negotiate authentication scheme not available
[DEBUG] [org.apache.http.impl.client.TargetAuthenticationStrategy] Challenge for Kerberos authentication scheme not available
[DEBUG] [org.apache.http.impl.client.TargetAuthenticationStrategy] Challenge for NTLM authentication scheme not available
[DEBUG] [org.apache.http.impl.client.TargetAuthenticationStrategy] Challenge for CredSSP authentication scheme not available
[DEBUG] [org.apache.http.impl.client.TargetAuthenticationStrategy] Challenge for Digest authentication scheme not available
[DEBUG] [org.apache.http.client.protocol.ResponseProcessCookies] Cookie accepted [__cf_bm="HtGYa8jbXjy6t35Tyqb9Nmyfvk3cld9G9.B6vyIj.YI-1763677277-1.0.1.1-DDrvJ4YXRIPGV3TqPTDw6ZwYrqHmlyEARxqnz...", version:0, domain:gitlab.com, path:/, expiry:Thu Nov 20 22:51:17 UTC 2025]
[DEBUG] [org.apache.http.client.protocol.ResponseProcessCookies] Cookie accepted [_cfuvid="jXmUcPoIG7Nc6m9lsn98iEaf_yli.jx7b3bxJerdUCA-1763677277259-0.0.1.1-604800000", version:0, domain:gitlab.com, path:/, expiry:null]
[DEBUG] [org.apache.http.impl.conn.PoolingHttpClientConnectionManager] Connection [id: 2][route: {s}->https://gitlab.com:443] can be kept alive indefinitely
[DEBUG] [org.apache.http.impl.conn.DefaultManagedHttpClientConnection] http-outgoing-2: set socket timeout to 0
[DEBUG] [org.apache.http.impl.conn.PoolingHttpClientConnectionManager] Connection released: [id: 2][route: {s}->https://gitlab.com:443][total available: 1; route allocated: 1 of 20; total allocated: 1 of 20]
[DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Build operation 'Upload https://gitlab.com/api/v4/projects/34294364/packages/maven/jpsgcs/jpsgcs/3.3.4-2/jpsgcs-3.3.4-2.jar' completed
[DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Build operation 'Execute publish for :publishLibraryPublicationToJpsgcsRepository' completed
[DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Build operation 'Executing task ':publishLibraryPublicationToJpsgcsRepository'' completed
[DEBUG] [org.gradle.internal.vfs.impl.AbstractVirtualFileSystem] Invalidating VFS paths: []
[DEBUG] [org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter] Removed task artifact state for task ':publishLibraryPublicationToJpsgcsRepository' from context.
[DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Completing Build operation 'Task :publishLibraryPublicationToJpsgcsRepository'
[DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Build operation 'Task :publishLibraryPublicationToJpsgcsRepository' completed
[DEBUG] [org.gradle.execution.plan.DefaultFinalizedExecutionPlan] Node :publishLibraryPublicationToJpsgcsRepository completed, executed: true
[DEBUG] [org.gradle.execution.plan.DefaultFinalizedExecutionPlan] Node :publishLibraryPublicationToJpsgcsRepository failed
[DEBUG] [org.gradle.execution.plan.DefaultFinalizedExecutionPlan] Node :publish completed, executed: false
[DEBUG] [org.gradle.internal.resources.AbstractTrackedResourceLock] Execution worker: released lock on state of build :
[DEBUG] [org.gradle.internal.resources.AbstractTrackedResourceLock] Execution worker: released lock on task execution for build :
[DEBUG] [org.gradle.internal.resources.AbstractTrackedResourceLock] included builds: acquired lock on worker lease
[DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Completing Build operation 'Run tasks'
[DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Build operation 'Run tasks' completed
[DEBUG] [org.gradle.internal.resources.AbstractTrackedResourceLock] included builds: released lock on worker lease
[DEBUG] [org.gradle.internal.resources.AbstractTrackedResourceLock] Daemon worker: acquired lock on worker lease
[DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Completing Build operation 'Run main tasks'
[DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Build operation 'Run main tasks' completed
[DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Build operation 'Finish root build tree' started
[DEBUG] [org.gradle.internal.resources.AbstractTrackedResourceLock] Execution worker: released lock on worker lease
[DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Completing Build operation 'Finish root build tree'
[DEBUG] [org.gradle.internal.operations.DefaultBuildOperationRunner] Build operation 'Finish root build tree' completed
[ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] 
[ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] FAILURE: Build failed with an exception.
[ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] 
[ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] * What went wrong:
[ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] Execution failed for task ':publishLibraryPublicationToJpsgcsRepository'.
[ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] > Failed to publish publication 'library' to repository 'jpsgcs'
[ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter]    > Could not PUT 'https://gitlab.com/api/v4/projects/34294364/packages/maven/jpsgcs/jpsgcs/3.3.4-2/jpsgcs-3.3.4-2.jar'. Received status code 401 from server: Unauthorized

I hope readers can undo the line wrap.