web-dev-qa-db-fra.com

Télécharger des artefacts sur Nexus, sans Maven

J'ai un projet non-Java qui produit un artefact de génération versionné, et je souhaite le télécharger dans un référentiel Nexus. Comme le projet n'est pas Java, il n'utilise pas Maven pour les versions. Et je préférerais ne pas introduire de fichiers Maven/POM uniquement pour importer des fichiers dans Nexus.

Les liens sur les blogs vers l'API Nexus REST se retrouvent tous sur un mur d'ouverture de session, sans lien de "création d'utilisateur" visible.

Alors, quel est le meilleur moyen (ou tout autre moyen raisonnable) de télécharger des artefacts de construction dans un référentiel Nexus sans Maven? "bash + curl" serait bien, ou même un script Python.

95
Adam Vandenberg

Avez-vous envisagé d'utiliser la ligne de commande Maven pour télécharger des fichiers?

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

Cela générera automatiquement le POM Maven pour l'artefact.

Mise à jour

L'article suivant de Sonatype indique que le plugin maven "deploy-file" est la solution la plus simple, mais il fournit également des exemples utilisant curl:

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

96
Mark O'Connor

En utilisant 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

Vous pouvez voir la signification des paramètres ici: https://support.sonatype.com/entries/22189106-How-can-I-programically-upload-an-artifact-into-Nexus-

Pour rendre les autorisations nécessaires pour ce travail, j'ai créé un nouveau rôle dans l'interface graphique de l'administrateur et j'ai ajouté deux privilèges à ce rôle: téléchargement d'artefact et téléchargement d'artefact. Le rôle standard "Repo: All Maven Repositories (Full Control)" - ne suffit pas. Vous ne le trouverez pas dans la documentation de l'API fournie avec le serveur Nexus REST), de sorte que ces paramètres risquent de changer à l'avenir.

Sur n problème de Sonatype JIRA , il a été mentionné qu'ils "vont réviser l'API REST (et la façon dont sa documentation est générée) dans une prochaine version, la plupart probablement plus tard cette année ".

62
Ed I

Vous n'avez pas besoin d'utiliser ces commandes. Vous pouvez directement utiliser l'interface Web nexus afin de télécharger votre fichier JAR à l'aide de paramètres GAV.

enter image description here

Donc c'est très simple.

8
Praneel PIDIKITI

Vous pouvez [~ # ~] absolument [~ # ~] faire cela sans utiliser quoi que ce soit qui est lié à MAVEN. Personnellement, j'utilise NING HttpClient (v1.8.16, pour supporter Java6).

Pour quelque raison que ce soit, Sonatype rend incroyablement difficile de déterminer quelles sont les adresses URL, en-têtes et données utiles correctes; et j’ai dû sentir le trafic et deviner ... Il y en a à peine blogs/documentation utiles, mais c’est soit indifférent à oss.sonatype.org, ou c'est basé sur XML (et j'ai découvert que cela ne fonctionnait même pas). La documentation de la merde de leur part, IMHO, et espérons que les futurs demandeurs pourront trouver cette réponse utile. Merci beaucoup à https://stackoverflow.com/a/33414423/2101812 pour leur message, car cela a beaucoup aidé.

Si vous relâchez quelque chose d'autre que oss.sonatype.org _, remplacez-le simplement par l'hôte correct.

Voici le code (sous licence CC0) que j'ai écrit pour accomplir cela. Où profile est votre identifiant de profil sonatype/nexus (tel que 4364f3bbaf163) et repo (comme comdorkbox-1003) sont analysés à partir de la réponse lorsque vous téléchargez votre POM/Jar initial.

Fermer le repo:

/**
 * 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);
}

Promouvoir 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);
}

Drop repo:

/**
 * 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);
}

Supprimer les signatures de signature:

/**
 * 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);
}

Fichiers téléchargés:

    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:

Comment obtenir l'activité/le statut d'un repo

/**
 * 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);
}
8
Nathan

Les appels que vous devez faire contre Nexus sont les appels REST api.

Le plugin maven-nexus est un plugin Maven que vous pouvez utiliser pour passer ces appels. Vous pouvez créer un pom factice avec les propriétés nécessaires et passer ces appels via le plugin Maven.

Quelque chose comme:

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

Choses supposées:

  1. Vous avez défini un serveur dans votre ~/.m2/settings.xml nommé sonatype-nexus-staging avec votre utilisateur sonatype et votre mot de passe configurés. Vous l'avez probablement déjà fait si vous déployez des instantanés. Mais vous pouvez trouver plus d'informations ici .
  2. Votre fichier settings.xml local inclut les plugins Nexus tels que spécifiés ici .
  3. Le pom.xml situé dans votre répertoire actuel a les bonnes coordonnées Maven dans sa définition. Si ce n'est pas le cas, vous pouvez spécifier le groupId, artifactId et la version sur la ligne de commande.
  4. Le -Dauto = true désactive les invites interactives pour vous permettre de créer un script.

En fin de compte, tout ce que nous faisons consiste à créer REST appelle dans Nexus. Il existe un Nexus complet REST api, mais j’ai eu peu de chance de trouver de la documentation à ce sujet. Vous pouvez activer le mode débogage pour le plugin ci-dessus et le comprendre en utilisant -Dnexus.verboseDebug=true -X.

Théoriquement, vous pouvez également accéder à l'interface utilisateur, activer le panneau Firebug Net, rechercher/traiter les messages POST et en déduire un chemin d'accès également.

6
Alex Miller

pour ceux qui en ont besoin en Java, utilisez 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;
    }
}
3
McMosfet

Vous pouvez également utiliser la méthode de déploiement direct à l'aide de curl. Vous n'avez pas besoin d'un pom pour votre fichier, mais il ne sera pas généré aussi. Si vous en voulez un, vous devrez le télécharger séparément.

Voici la commande:

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
2
Djidiouf

In Ruby https://github.com/RiotGames/nexus_cli Un wrapper CLI autour de Sonatype Nexus REST appelle.

Exemple d'utilisation:

nexus-cli Push_artifact com.mycompany.artifacts:myartifact:tgz:1.0.0 ~/path/to/file/to/Push/myartifact.tgz

La configuration se fait via le .nexus_cli fichier.

url:            "http://my-nexus-server/nexus/"
repository:     "my-repository-id"
username:       "username"
password:       "password"
1
Francois

Si vous avez besoin d'une interface de ligne de commande pratique ou python, consultez repositorytools

En l’utilisant, vous pouvez télécharger un artefact sur Nexus avec la commande

artifact upload foo-1.2.3.ext releases com.fooware

Pour que cela fonctionne, vous devrez également définir des variables d’environnement.

export REPOSITORY_URL=https://repo.example.com
export REPOSITORY_USER=admin
export REPOSITORY_PASSWORD=mysecretpassword
1
Michel Samia

Pour les versions récentes de Nexus OSS (> = 3.9.0)

https://support.sonatype.com/hc/en-us/articles/115006744008-How-can-I-programmatically-upload-files-into-Nexus-3-

Exemple pour les versions 3.9.0 à 3.13.0:

curl -D - -u user:pass -X POST "https://nexus.domain/nexus/service/rest/beta/components?repository=somerepo" -H "accept: application/json" -H "Content-Type: multipart/form-data" -F "raw.directory=/test/" -F "[email protected];type=application/json" -F "raw.asset1.filename=test.txt"
0
adrianlzt

Vous pouvez télécharger manuellement les artefacts en cliquant sur le bouton Télécharger des artefacts sur le serveur Nexus et fournir les propriétés GAV nécessaires pour le téléchargement (il s'agit généralement de la structure de fichier permettant de stocker l'artefact).

0
jijendiran