How can I programmatically upload an artifact into Nexus?

There are several ways to upload artifacts into Nexus without running a build.

Direct Deploy

You can do an HTTP PUT of a file into /content/repositories/<repo-id>/<path-of-file>.  Using curl you can do this with:

curl -v -u admin:admin123 --upload-file pom.xml http://localhost:8081/nexus/content/repositories/releases/org/foo/1.0/foo-1.0.pom

Maven "deploy-file" Deployment

You can deploy files using the "deploy-file" goal on the Maven deploy plugin

Example without a pom file:

mvn deploy:deploy-file -DgroupId=com.somecompany -DartifactId=project -Dversion=1.0.0 -DgeneratePom=true -Dpackaging=jar -DrepositoryId=nexus -Durl=http://localhost:8081/nexus/content/repositories/releases -Dfile=target/project-1.0.0.jar

With a pom file:

mvn deploy:deploy-file -DgroupId=com.somecompany -DartifactId=project -Dversion=1.0.0 -DgeneratePom=false -Dpackaging=jar -DrepositoryId=nexus -Durl=http://localhost:8081/nexus/content/repositories/releases -DpomFile=pom.xml -Dfile=target/project-1.0.0.jar

This plugin goal also allows deployment of snapshot versions, and the plugin will take care of calculating the timestamped version needed:

mvn deploy:deploy-file -DgroupId=com.somecompany -DartifactId=project -Dversion=1.0.0-SNAPSHOT -DgeneratePom=true -Dpackaging=jar -DrepositoryId=nexus -Durl=http://localhost:8081/nexus/content/repositories/snapshots -Dfile=target/project-1.0.0-SNAPSHOT.jar

Note: The "repositoryId" parameter is not a Nexus repository ID, it is the ID of a server section in your settings.xml file which has then credentials needed for deployment.

<servers>
...
  <server>
      <id>nexus</id>
      <username>deployment</username>
      <password>deployment123</password>
    </server>
  </servers>

REST API Upload

Alternatively you can use the REST API.  This requires a multi-part form POST to /service/local/artifact/maven/content.

Here are some examples using curl.

1) Uploading an artifact and generating a pom file:

curl -v -F r=releases -F hasPom=false -F e=jar -F g=com.test -F a=project -F v=1.0 -F p=jar -F file=@project-1.0.jar -u admin:admin123 http://localhost:8081/nexus/service/local/artifact/maven/content

2) Uploading an artifact with a pom file:

curl -v -F r=releases -F hasPom=true -F e=jar -F file=@pom.xml -F file=@project-1.0.jar -u admin:admin123 http://localhost:8081/nexus/service/local/artifact/maven/content

3) Uploading a pom file by itself (with no artifact):

curl -v -F r=releases -F hasPom=true -F file=@pom.xml -u admin:admin123 http://localhost:8081/nexus/service/local/artifact/maven/content
Important: The file parameters MUST COME LAST or the curl commands will not work. If you are uploading a pom file, then the pom file parameter must come before the rest of the file parameters, but after all the other parameters.

For reference, here are all the available form parameters for this endpoint:

r : repository

hasPom - whether you are supplying the pom or you want one generated. If you are uploading a pom, then the parameters g, a, v, p, and c are not needed as part of the command as those values are extracted from the pom.ml

e - extension

g - group id

a - artifact id

v - version

p - packaging

c - classifier (optional, not shown in examples above)

file - each file to be uploaded, use one file parameter per file.

Note: Uploading via the REST API requires that the user has the "artifact upload" privilege in Nexus, in addition to create and update privileges on the target repository.

Uploading Multiple Artifacts at Once

Enable the Nexus Unpack Plugin

In Nexus Professional 2.7.x+, the plugin is already installed by default.

In Nexus Professional 2.6.x and earlier, the optional plugin needs to be installed. You can enable this plugin in earlier versions of Nexus Professional by moving "$NEXUS_HOME/nexus/WEB-INF/optional-plugins/nexus-unpack-plugin-<version>" into "$NEXUS_HOME/nexus/WEB-INF/plugin-repository" and restarting the server.

In Nexus OSS you need to manually install the plugin.  Download the bundle.zip which matches your nexus version, and unpack it in $NEXUS_HOME/nexus/WEB-INF/plugin-repository. Then restart the server.

Use the Nexus Unpack Plugin

Once enabled, you can use a REST endpoint to upload zip files via PUT request. This takes the form of (ensure that there is no trailing slash in the URL):

/service/local/repositories/{repositoryId}/content-compressed/path/you/want/them/to/appear/in

So for example, using curl:

curl --upload-file my.zip -u admin:admin123 -v http://localhost:8081/nexus/service/local/repositories/releases/content-compressed/foo/bar

The files will be unpacked and deployed individually on the server side, just as if they had been individually deployed from a client using standard deploy mechanisms.

If the zipped file has a directory structure of "com/company/project/...", then you want to deploy to the root level of repository.

curl --upload-file my.zip -u admin:admin123 -v http://localhost:8081/nexus/service/local/repositories/releases/content-compressed

If the zipped file has a directory structure example of "project/...", then you want to deploy to the "com/company" level of repository.

curl --upload-file my.zip -u admin:admin123 -v http://localhost:8081/nexus/service/local/repositories/releases/content-compressed/com/company

Note that the user performing this deploy must have the "Unpack" privilege in Nexus, as well as create privileges in the target repository.

Also note that the files in the zip must be in the standard repository layout of the target repository.

Uploading using Powershell

We have a blog post which describes how to upload artifacts using Powershell.

Have more questions? Submit a request

45 Comments

  • 0
    Avatar
    Roger Huang

    Rich thanks for the explanation.

  • 0
    Avatar
    David Portabella

    I guess there is a type on "http://localhost:8081/nexus/service/local/artifact/maven/content".

    It should be "http://localhost:8081/service/local/artifact/maven/content", right?

    another question, why is this feature not documented?

    according to the doc, this url can only make a GET, not a POST operation:

    http://localhost/nexus-core-documentation-plugin/core/docs/rest.artifact.maven.content.html

  • 0
    Avatar
    David Portabella

    Another question,

    this REST api worked for me for uploading a release artifact in a release repository.

    however, when I try uploading a snapshot artifact in a snaphost repository, I get this error:

    HTTP/1.1 405 Method Not Allowed

    <p>The method specified in the request is not allowed for the resource identified by the request URI</p>

    why is that?

    according to the source code: https://repository.sonatype.org/content/sites/maven-sites/nexus-oss/nexus/nexus-rest-api/xref/org/sonatype/nexus/rest/artifact/AbstractArtifactPlexusResource.html

    // temporarily we disable SNAPSHOT upload
    431 // check is it a Snapshot repo
    432 if ( RepositoryPolicy.SNAPSHOT.equals( mr.getRepositoryPolicy() ) ) {
    435
    436 throw new ResourceException( Status.CLIENT_ERROR_BAD_REQUEST, "This is a Maven SNAPSHOT repository, and manual upload against it is forbidden!" );
    438 }

    however, when I try uploading a snapshot artifact in a snaphost repository, using the mvn deploy plugin, then it works.

    ???

  • 0
    Avatar
    Rich Seddon

    In answer to the first question, it depends on what the application context is set to. In a stock configuration of Nexus we ship with it running on "/nexus".

    I'll file a bug for the missing documentation.

    Regarding snapshot upload, this is explicitly disallowed by Nexus, the thought is it promotes bad practices. If you need to rely on a snapshot artifact for a long period of time you should rename it as a release:

    https://issues.sonatype.org/browse/NEXUS-1036

     

  • 0
    Avatar
    David Portabella

    thanks for the quick reply.

    why is it a bad practice to upload snapshots using REST api,

    while at the same time it is a good practice to upload snapshots using mvn deploy?

  • 0
    Avatar
    Neil Bartlett

    I'm very curious about this as well, it's a pity that Sonatype stopped responding. Why is it okay to deploy to snapshot repos with mvn:deploy but not with the REST API??

    Uploading with the API doesn't imply anything about how long you intend to use the artifact for after deployment.

    Is there *any* way to deploy into a snapshot repository besides mvn:deploy? It seems like this prevents practical use of Nexus with any other build tool.

  • 0
    Avatar
    Rich Seddon

    Programatically uploading a snapshot into nexus requires downloading the maven-metadata.xml file, calculating the next build number, updating the maven-metadata.xml file, uploading it, and uploading the pom and artifact files.

    This is doable, but it will add complexity to the upload. And for most use cases, uploading a snapshot manually really isn't the right thing to do.  Snapshots are temporary things, usually produced by CI systems, and will likely be cleaned up by the snapshot remover over time.  If you really  need to depend on a snapshot artifact the recommendation is to rename it to a release GAV.

    That said, I think a lot of the concern about this feature is related to UI upload, not necessarily REST API upload.  There may be valid use cases to consider here, especially if snapshots are being produced in a CI system by something other than Maven.  Is that the case for you?

  • 0
    Avatar
    Neil Bartlett

    Thank you for your response. Yes that is essentially my use-case, I am integrating Nexus into a custom build process, and the CI outputs are really "snapshots" in the same sense as Maven's snapshots.

    However Maven seems to add a fair bit of additional semantics and metadata to the concept of a "snapshot". This is something I don't fully understand yet, not being a Maven user myself. It seems that most of the difference in Nexus between snapshot and release repos exists to support Maven's model of a snapshot, and so is not needed in my use-case. Therefore a Release repo may simply be the right choice in this case.

    Having said that, non-Maven build tools clearly do need the ability to push into Nexus snapshot repos for consumption by Nexus. For example Gradle appears to have a way to do this. I guess that they have probably reversed engineered whatever the mvn:deploy task does. If so, it's a shame that they have to do this rather than using documented, supported APIs.

  • 0
    Avatar
    Martin Gainty

    Allow GET and POST..allow upload of SNAPSHOT and RELEASE ..let the client decide what not to do
    this makes for happier clients...Happy Clients == $

  • 0
    Avatar
    David Portabella

    Programatically uploading a snapshot into nexus requires downloading the maven-metadata.xml file,

    calculating the next build number, updating the maven-metadata.xml file, uploading it, and uploading the pom and artifact files.

    This logic should be implemented on the server-side, not on the client-side.

    bad design!

     

  • 0
    Avatar
    Rich Seddon

    Maven is designed to work with any sort of repository, even those being hosted in a simple web server such as Apache.  Consequentially this logic needed to be implemented on the client side.

    We will take a look at allowing REST upload of snapshot artifacts, but this will happen after the Nexus 3.0 release is complete later this year.

  • 0
    Avatar
    David Hladky

    .I tried this plugin on version 2.8.0-05 and it does not do the thing described here. If I quote Rich:

    The files will be unpacked and deployed individually on the server side, just as if they had been individually deployed from a client using standard deploy mechanisms.

    This would be very helpful feature for us, because we need to deploy a big amount of artifacts at once and it would be great if the files were deployed as described in your article. When I use your example:

    curl --upload-file my.zip -u admin:admin123 -v http://192.168.1.50:8081/nexus/service/local/repositories/releases/content-compressed/foo/bar

    The files are not expanded in /releases/content-compressed/foo/bar/ but in /releases/content-compressed/foo/bar/my.zip

    No checksums are created nor maven-metadata.xml files are updated. Is that intentional behaviour?

    I suppose Maven will not be able to find artifacts in such "expanded" zip, unless the repository is set directly to the specific zip. Is that right? Is there any way to download the my.zip again in its original (packed) form?

  • 0
    Avatar
    Rich Seddon

    "No checksums are created nor maven-metadata.xml files are updated. Is that intentional behaviour?"

    No, the zip should be expanded.  What format is the zip file in?  It needs to contain artifacts that are in a valid m2 repository layout.

  • 0
    Avatar
    David Hladky

    I created a normal zip file with files 'download-manager-2.0.8-javadoc.jar' 'download-manager-2.0.8-sources.jar' 'download-manager-2.0.8.pom' 'download-manager-2.0.8.war' (all directly in root). The war was a web archive I used for experiments with Maven deploys, the pom was a valid pom.xml renamed to this form sources and javadoc were generated by Maven plugins - sources and javadoc. All the files were in the root of the ZIP.

     

    I thought, that when I use

    curl --upload-file audit.zip -u admin:admin123 -v http://localhost:8081/service/local/repositories/releases/content-compressed/org/jboss/download-manager/2.0.8/

    they will be deployed to 2.0.8. However a new folder /org/jboss/download-manager/2.0.8/audit.zip/ was created and the mentioned files were expanded there (no checksums appeared).

  • 0
    Avatar
    Rich Seddon

    Hi David,

    The "audit.zip" directory is getting created because of the trailing "/" on your URL (unfortunately restlet is sensitive to this). Try leaving that off. 

    It's not expected that checksums will be generated, only the files in the zip will be deployed.  You can force the regeneration of checksums by rebuilding metadata, to do this with curl use:

    curl -v -u userID:password -X DELETE http://localhost:8081/nexus/service/local/metadata/repositories/<repo-id>/content/path/to/folder/

    Rich

  • 0
    Avatar
    Grégory Joseph

    I did not know about the /content-compressed endpoint, this is pretty cool ! Is there, by chance, any way to make this work with the Maven Site plugin and it's deploy goal ? In the olden days, we were deploy sites over ssh, and this was the default behavior: zip up generate site, scp and unzip it remotely. Nowaways, we deploy over dav, and it's a pretty flaky, slow and tedious process, as each file of the site is deployed one by one (which becomes terrible when you factor javadoc in). I'd love to be able to upload zips again.

  • 0
    Avatar
    Rich Seddon

    The content-compressed endpoint works with the site plugin. You just need to jar the update site with site:jar

    http://maven.apache.org/plugins/maven-site-plugin/jar-mojo.html

    And then you can upload it to the site repository's content-compressed endpoint using wagon:upload or similar.

  • 0
    Avatar
    Grégory Joseph

    Mind. Blown.

    Thanks Rich !

  • 0
    Avatar
    Grégory Joseph

    Oh wait, yeah - I meant "automatically", just like the nexus-staging-plugin "replaces" the regular deploy plugin

  • 0
    Avatar
    Pim

    I also tried doing this and failed to far.

    My call is fine (or at least nexus knows what to do with it), but in the end the nexus.log reports:

    org.sonatype.sisu.siesta.server.internal.mappers.WebApplicationExceptionMapper - (ID e0b1535d-7d80-4cab-affa-11

    830970be84) Response: [412] ErrorXO{id='e0b1535d-7d80-4cab-affa-11830970be84', message='412 Precondition Failed'} mapped from javax.ws.rs.WebApplicationException/null

    I've tried to get more information on this error, but the only reasonable search hits were in some Asian language I can not read.

    Also I gave the user every possible permission that was available (since the Nexus roles and permissions especially with the API and the UI are very unclear to me)

    Would have been really nice if Sonatype would have made an effort in describing the API and provide a troubleshooter or decent logging such that the user can get a clue on whats wrong.

    Please advice

  • 0
    Avatar
    Rich Seddon

    The "precondition failed" error indicates something is wrong with your request, it is not a permission problem.  What request was being sent?

  • 0
    Avatar
    Pim

    What I did were the exact same arguments as this one with values matching my nexus:

    curl -v -F r=releases -F hasPom=false -F e=jar -F g=com.test -F a=project -F v=1.0 -F p=jar -F file=@project-1.0.jar -u admin:admin123 http://localhost:8081/nexus/service/local/artifact/maven/content

  • 0
    Avatar
    Pim

    Btw. Nexus version 2.8.1-01

  • 0
    Avatar
    Rich Seddon

    I'll need to see your logs and configuration. Reproduce the issue, then generate a support zip under "administration/support tools/support zip" in the UI, and submit a ticket.

    Regards,

    Rich

  • 0
    Avatar
    Vineet Gupta

    just to address  , I was able to upload the artifact from simple curl command to Snapshot repo too now - Not sure it's not been supported in Nexus 2.x now ? 

    curl -v -F "r=Snapshots" -F "g=com.name" -F "a=<artifact>" -F "v=<version>" -F "p=deb" -F "file=@filename" -u admin:password http://localhost:8081/nexus/content/repositories/snapshots/directory-tree/filename

  • 0
    Avatar
    Rich Seddon

    REST API deployment of snapshots isn't supported.  You can use the Maven deploy plugin's "deploy-file" goal to deploy snapshot versions into Nexus, I've added an example in the article.

  • 0
    Avatar
    Ritesh Keloth

    Hi Rich,

    Does it also have dependency on the edition of Nexus being used ? I have Nexus OSS, I am tryng to use the REST API method to upload artifacts to the Nexus Repository of type "release". But getting the below error.
    "HTTP/1.1 405 Method Not Allowed"

  • 0
    Avatar
    Rich Seddon

    The article applies to both Nexus Pro and Nexus OSS. If you're getting error 405 there is something wrong with the command you are using to upload.

  • 0
    Avatar
    David Hladky

    The plugin used not to be present in the OSS version, but was freely available, correct?

  • 0
    Avatar
    Rich Seddon

    The nexus-unpack-plugin?  Yes, it's freely available for Nexus OSS, the  link is in the article above.

Article is closed for comments.
Powered by Zendesk