Sube artefactos a Nexus, sin Maven

Tengo un proyecto que no es Java que produce un artefacto de construcción versionado y quiero subirlo a un repository de Nexus. Como el proyecto no es Java, no usa Maven para comstackciones. Y prefiero no presentar archivos Maven / POM solo para obtener archivos en Nexus.

Los enlaces en los blogs a la API de REST de Nexus terminan en un muro de inicio de sesión, sin ningún vínculo de “crear usuario” que pueda ver.

Entonces, ¿cuál es la mejor (o razonable) forma de subir artefactos de construcción a un repository Nexus sin Maven? “bash + curl” sería genial, o incluso una secuencia de comandos de Python.

¿Has pensado utilizar la línea de comandos de Maven para subir archivos?

mvn deploy:deploy-file \ -Durl=$REPO_URL \ -DrepositoryId=$REPO_ID \ -DgroupId=org.myorg \ -DartifactId=myproj \ -Dversion=1.2.3 \ -Dpackaging=zip \ -Dfile=myproj.zip 

Esto generará automáticamente el Maven POM para el artefacto.

Actualizar

El siguiente artículo de Sonatype establece que el plugin maven “deploy-file” es la solución más fácil, pero también proporciona algunos ejemplos que usan curl:

https://support.sonatype.com/entries/22189106-How-can-I-progtwigtically-upload-an-artifact-into-Nexus-

Usando curl:

 curl -v \ -F "r=releases" \ -F "g=com.acme.widgets" \ -F "a=widget" \ -F "v=0.1-1" \ -F "p=tar.gz" \ -F "file=@./widget-0.1-1.tar.gz" \ -u myuser:mypassword \ http://localhost:8081/nexus/service/local/artifact/maven/content 

Puede ver lo que significan los parámetros aquí: https://support.sonatype.com/entries/22189106-How-can-I-progtwigtically-upload-an-artifact-into-Nexus-

Para otorgar los permisos para este trabajo, creé un nuevo rol en la GUI de administración y agregué dos privilegios a esa función: Descarga de artefactos y carga de artefactos. El estándar “Repo: todos los repositorys Maven (control total)”: el rol no es suficiente. No encontrará esto en la documentación de la API REST que viene incluida con el servidor Nexus, por lo que estos parámetros podrían cambiar en el futuro.

En un problema Sonatype JIRA , se mencionó que “van a revisar la API REST (y la forma en que se genera la documentación) en una próxima versión, muy probablemente a finales de este año”.

Puedes ABSOLUTAMENTE hacer esto sin usar nada relacionado con MAVEN. Yo personalmente uso el NING HttpClient (v1.8.16, para admitir java6).

Por alguna razón, Sonatype hace que sea increíblemente difícil averiguar cuáles son las URL, los encabezados y las cargas útiles correctos. y tuve que olfatear el tráfico y adivinar … Hay algunos blogs / documentación apenas útiles allí, sin embargo, es irrelevante para oss.sonatype.org , o está basado en XML (y descubrí que ni siquiera funciona) . La documentación de mierda por su parte, en mi humilde opinión, y con suerte los futuros buscadores pueden encontrar esta respuesta útil. Muchas gracias a https://stackoverflow.com/a/33414423/2101812 por su publicación, ya que ayudó mucho.

Si publica otro sitio que no sea oss.sonatype.org , simplemente reemplácelo con el host correcto.

Aquí está el código (con licencia CC0) que escribí para lograr esto. Donde profile es su sonatype / nexus profileID (como 4364f3bbaf163 ) y repo (como comdorkbox-1003 ) se analizan a partir de la respuesta cuando carga su POM / Jar inicial.

Cerrar repository:

 /** * Closes the repo and (the server) will verify everything is correct. * @throws IOException */ private static String closeRepo(final String authInfo, final String profile, final String repo, final String nameAndVersion) throws IOException { String repoInfo = "{'data':{'stagedRepositoryId':'" + repo + "','description':'Closing " + nameAndVersion + "'}}"; RequestBuilder builder = new RequestBuilder("POST"); Request request = builder.setUrl("https://oss.sonatype.org/service/local/staging/profiles/" + profile + "/finish") .addHeader("Content-Type", "application/json") .addHeader("Authorization", "Basic " + authInfo) .setBody(repoInfo.getBytes(OS.UTF_8)) .build(); return sendHttpRequest(request); } 

Promover repo:

 /** * Promotes (ie: release) the repo. Make sure to drop when done * @throws IOException */ private static String promoteRepo(final String authInfo, final String profile, final String repo, final String nameAndVersion) throws IOException { String repoInfo = "{'data':{'stagedRepositoryId':'" + repo + "','description':'Promoting " + nameAndVersion + "'}}"; RequestBuilder builder = new RequestBuilder("POST"); Request request = builder.setUrl("https://oss.sonatype.org/service/local/staging/profiles/" + profile + "/promote") .addHeader("Content-Type", "application/json") .addHeader("Authorization", "Basic " + authInfo) .setBody(repoInfo.getBytes(OS.UTF_8)) .build(); return sendHttpRequest(request); } 

Repo de gota:

 /** * Drops the repo * @throws IOException */ private static String dropRepo(final String authInfo, final String profile, final String repo, final String nameAndVersion) throws IOException { String repoInfo = "{'data':{'stagedRepositoryId':'" + repo + "','description':'Dropping " + nameAndVersion + "'}}"; RequestBuilder builder = new RequestBuilder("POST"); Request request = builder.setUrl("https://oss.sonatype.org/service/local/staging/profiles/" + profile + "/drop") .addHeader("Content-Type", "application/json") .addHeader("Authorization", "Basic " + authInfo) .setBody(repoInfo.getBytes(OS.UTF_8)) .build(); return sendHttpRequest(request); } 

Eliminar comstackción de firmas:

 /** * Deletes the extra .asc.md5 and .asc.sh1 'turds' that show-up when you upload the signature file. And yes, 'turds' is from sonatype * themselves. See: https://issues.sonatype.org/browse/NEXUS-4906 * @throws IOException */ private static void deleteSignatureTurds(final String authInfo, final String repo, final String groupId_asPath, final String name, final String version, final File signatureFile) throws IOException { String delURL = "https://oss.sonatype.org/service/local/repositories/" + repo + "/content/" + groupId_asPath + "/" + name + "/" + version + "/" + signatureFile.getName(); RequestBuilder builder; Request request; builder = new RequestBuilder("DELETE"); request = builder.setUrl(delURL + ".sha1") .addHeader("Authorization", "Basic " + authInfo) .build(); sendHttpRequest(request); builder = new RequestBuilder("DELETE"); request = builder.setUrl(delURL + ".md5") .addHeader("Authorization", "Basic " + authInfo) .build(); sendHttpRequest(request); } 

Cargas de archivos:

  public String upload(final File file, final String extension, String classification) throws IOException { final RequestBuilder builder = new RequestBuilder("POST"); final RequestBuilder requestBuilder = builder.setUrl(uploadURL); requestBuilder.addHeader("Authorization", "Basic " + authInfo) .addBodyPart(new StringPart("r", repo)) .addBodyPart(new StringPart("g", groupId)) .addBodyPart(new StringPart("a", name)) .addBodyPart(new StringPart("v", version)) .addBodyPart(new StringPart("p", "jar")) .addBodyPart(new StringPart("e", extension)) .addBodyPart(new StringPart("desc", description)); if (classification != null) { requestBuilder.addBodyPart(new StringPart("c", classification)); } requestBuilder.addBodyPart(new FilePart("file", file)); final Request request = requestBuilder.build(); return sendHttpRequest(request); } 

EDIT1:

Cómo obtener la actividad / estado de un repository

 /** * Gets the activity information for a repo. If there is a failure during verification/finish -- this will provide what it was. * @throws IOException */ private static String activityForRepo(final String authInfo, final String repo) throws IOException { RequestBuilder builder = new RequestBuilder("GET"); Request request = builder.setUrl("https://oss.sonatype.org/service/local/staging/repository/" + repo + "/activity") .addHeader("Content-Type", "application/json") .addHeader("Authorization", "Basic " + authInfo) .build(); return sendHttpRequest(request); } 

No es necesario utilizar estos comandos … puede usar directamente la interfaz web nexus para cargar su JAR utilizando los parámetros de GAV.

enter image description here

Entonces es muy simple.

Las llamadas que debe realizar contra Nexus son llamadas REST api.

El plugin maven-nexus es un plugin Maven que puede usar para realizar estas llamadas. Podrías crear un pom ficticio con las propiedades necesarias y hacer esas llamadas a través del plugin Maven.

Algo como:

 mvn -DserverAuthId=sonatype-nexus-staging -Dauto=true nexus:staging-close 

Cosas asumidas:

  1. Ha definido un servidor en su ~ / .m2 / settings.xml llamado sonatype-nexus-staging con su usuario de sonatype y contraseña configurados; probablemente ya lo habrá hecho si está implementando snapshots. Pero puedes encontrar más información aquí .
  2. Su settings.xml local incluye los complementos nexus como se especifica aquí .
  3. El pom.xml que se encuentra en su directorio actual tiene las coordenadas correctas de Maven en su definición. De lo contrario, puede especificar groupId, artifactId y version en la línea de comando.
  4. El -Dauto = true desactivará las indicaciones interactivas para que pueda escribir esto.

En última instancia, todo lo que está haciendo es crear llamadas REST en Nexus. Hay una API completa de REST de Nexus, pero he tenido poca suerte para encontrar documentación que no esté detrás de un muro de pago. Puede activar el modo de depuración para el complemento anterior y resolverlo utilizando -Dnexus.verboseDebug=true -X .

También teóricamente puedes acceder a la interfaz de usuario, activar el panel Firebug Net y buscar / enviar POST y deducir un camino allí también.

para aquellos que lo necesitan en Java, utilizando apache httpcomponents 4.0:

 public class PostFile { protected HttpPost httppost ; protected MultipartEntity mpEntity; protected File filePath; public PostFile(final String fullUrl, final String filePath){ this.httppost = new HttpPost(fullUrl); this.filePath = new File(filePath); this.mpEntity = new MultipartEntity(); } public void authenticate(String user, String password){ String encoding = new String(Base64.encodeBase64((user+":"+password).getBytes())); httppost.setHeader("Authorization", "Basic " + encoding); } private void addParts() throws UnsupportedEncodingException{ mpEntity.addPart("r", new StringBody("repository id")); mpEntity.addPart("g", new StringBody("group id")); mpEntity.addPart("a", new StringBody("artifact id")); mpEntity.addPart("v", new StringBody("version")); mpEntity.addPart("p", new StringBody("packaging")); mpEntity.addPart("e", new StringBody("extension")); mpEntity.addPart("file", new FileBody(this.filePath)); } public String post() throws ClientProtocolException, IOException { HttpClient httpclient = new DefaultHttpClient(); httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1); addParts(); httppost.setEntity(mpEntity); HttpResponse response = httpclient.execute(httppost); System.out.println("executing request " + httppost.getRequestLine()); System.out.println(httppost.getEntity().getContentLength()); HttpEntity resEntity = response.getEntity(); String statusLine = response.getStatusLine().toString(); System.out.println(statusLine); if (resEntity != null) { System.out.println(EntityUtils.toString(resEntity)); } if (resEntity != null) { resEntity.consumeContent(); } return statusLine; } } 

Curl es el camino más difícil. Si no desea usar maven (p. Ej .: no permitido)

Eche un vistazo a la hiedra :

Otra opción gradle : http://www.gradle.org/docs/current/userguide/artifact_management.html#N14566

En ruby https://github.com/RiotGames/nexus_cli Un contenedor CLI alrededor de las llamadas REST Sonatype Nexus.

También puede usar el método de despliegue directo usando curl. No necesita un pom para su archivo, pero tampoco se generará así que si quiere uno, tendrá que cargarlo por separado.

Aquí está el comando:

 version=1.2.3 artefact="myartefact" repoId=yourrepository groupId=org.myorg REPO_URL=http://localhost:8081/nexus curl -u nexususername:nexuspassword --upload-file filename.tgz $REPO_URL/content/repositories/$repoId/$groupId/$artefact/$version/$artefact-$version.tgz 

Si necesita una interfaz de línea de comando conveniente o una API de Python, mire repositorytools

Puedes usar curl en su lugar.

 version=1.2.3 artifact="artifact" repoId=repositoryId groupId=org/myorg REPO_URL=http://localhost:8081/nexus curl -u username:password --upload-file filename.tgz $REPO_URL/content/repositories/$repoId/$groupId/$artefact/$version/$artifact-$version.tgz