webentwicklung-frage-antwort-db.com.de

Laden Sie Artefakte auf Nexus hoch, ohne Maven

Ich habe ein Nicht-Java-Projekt, das ein versioniertes Build-Artefakt erzeugt, und ich möchte dieses in ein Nexus-Repository hochladen. Da das Projekt nicht Java ist, wird Maven nicht für Builds verwendet. Und ich würde lieber keine Maven/POM-Dateien einführen, nur um Dateien in Nexus zu bekommen.

Die Links in Blogs zur Nexus REST API enden alle an einer Anmeldewand, ohne dass ein Link zum Erstellen eines Benutzers angezeigt wird.

Was ist die beste (oder vernünftigste) Möglichkeit, Build-Artefakte ohne Maven in ein Nexus-Repository hochzuladen? "bash + curl" wäre toll oder sogar ein Python script.

95
Adam Vandenberg

Haben Sie darüber nachgedacht, die Maven-Befehlszeile zum Hochladen von Dateien zu verwenden?

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

Dadurch wird automatisch der Maven POM für das Artefakt generiert.

Aktualisieren

Der folgende Sonatype-Artikel gibt an, dass das Maven-Plugin "deploy-file" die einfachste Lösung ist, enthält jedoch auch einige Beispiele für die Verwendung von curl:

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

96
Mark O'Connor

Curl verwenden:

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

Hier können Sie sehen, was die Parameter bedeuten: https://support.sonatype.com/entries/22189106-How-can-I-programatically-upload-an-artifact-into-Nexus-

Um die Berechtigungen für diese Funktion festzulegen, habe ich eine neue Rolle in der Admin-GUI erstellt und dieser Rolle zwei Berechtigungen hinzugefügt: Artefakt-Download und Artefakt-Upload. Die Standard-Rolle "Repo: Alle Maven-Repositorys (Vollzugriff)" reicht nicht aus. Sie finden dies nicht in der REST API-Dokumentation, die im Lieferumfang des Nexus-Servers enthalten ist. Daher können sich diese Parameter in Zukunft ändern.

Am ein Sonatype JIRA-Problem wurde erwähnt, dass sie "die REST API und die Art und Weise, wie die Dokumentation erstellt wird) in einer kommenden Version am meisten überarbeiten werden wahrscheinlich später in diesem Jahr ".

62
Ed I

Diese Befehle müssen nicht verwendet werden. Sie können das Nexus-Webinterface direkt verwenden, um Ihre JAR mithilfe der GAV-Parameter hochzuladen.

enter image description here

Es ist also sehr einfach.

8

Sie können dies [~ # ~] absolut [~ # ~] tun, ohne MAVEN zu verwenden. Ich persönlich benutze den NING HttpClient (v1.8.16, um Java6 zu unterstützen).

Aus irgendeinem Grund macht es Sonatype unglaublich schwierig, die richtigen URLs, Header und Nutzdaten zu ermitteln. und ich musste den Verkehr riechen und raten ... Es gibt einige kaum nützliche Blogs/Dokumentationen, aber es ist entweder irrelevant für oss.sonatype.org, oder es ist XML-basiert (und ich fand heraus, dass es nicht einmal funktioniert). Mistdokumentation ihrerseits, IMHO, und hoffentlich zukünftige Suchende können diese Antwort nützlich finden. Vielen Dank an https://stackoverflow.com/a/33414423/2101812 für den Beitrag, der sehr geholfen hat.

Wenn Sie irgendwo anders als oss.sonatype.org, ersetzen Sie es einfach durch den richtigen Host.

Hier ist der (CC0-lizenzierte) Code, den ich geschrieben habe, um dies zu erreichen. Wobei profile Ihre Sonatype/Nexus-Profil-ID ist (z. B. 4364f3bbaf163) und repo (wie comdorkbox-1003) werden aus der Antwort analysiert, wenn Sie Ihr erstes POM/Jar hochladen.

Repo schließen:

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

Repo bewerben:

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

Unterschriftenreste löschen:

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

Datei-Uploads:

    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:

So erhalten Sie die Aktivität/den Status für ein 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

Die Anrufe, die Sie gegen Nexus tätigen müssen, sind REST api calls.

Das Maven-Nexus-Plugin ist ein Maven-Plugin, mit dem Sie diese Anrufe tätigen können. Sie können einen Pseudo-Pom mit den erforderlichen Eigenschaften erstellen und diese Anrufe über das Maven-Plugin tätigen.

So etwas wie:

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

Angenommene Dinge:

  1. Sie haben in Ihrer Datei ~/.m2/settings.xml einen Server mit dem Namen sonatype-nexus-staging mit Ihrem eingerichteten Sonatype-Benutzer und Kennwort definiert. Dies ist wahrscheinlich bereits geschehen, wenn Sie Snapshots bereitstellen. Aber Sie können mehr Info finden hier .
  2. Ihre lokale settings.xml enthält die angegebenen Nexus-Plugins hier .
  3. Die Datei pom.xml in Ihrem aktuellen Verzeichnis enthält die korrekten Maven-Koordinaten. Andernfalls können Sie die Gruppen-ID, die Artefakt-ID und die Version in der Befehlszeile angeben.
  4. Mit -Dauto = true werden die interaktiven Eingabeaufforderungen deaktiviert, sodass Sie dies als Skript ausführen können.

Letztendlich müssen nur REST Aufrufe in Nexus erstellt werden. Es gibt einen vollständigen Nexus REST api, aber ich hatte wenig Glück, eine Dokumentation dafür zu finden, die nicht vorhanden ist hinter einer Paywall. Sie können den Debug-Modus für das Plugin oben aktivieren und es jedoch herausfinden, indem Sie -Dnexus.verboseDebug=true -X.

Sie können theoretisch auch die Benutzeroberfläche aufrufen, das Firebug Net-Bedienfeld einschalten, nach POSTs suchen/diese warten und dort auch einen Pfad ableiten.

6
Alex Miller

für diejenigen, die es in Java benötigen, mit 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

Sie können auch die direkte Bereitstellungsmethode mit curl verwenden. Sie brauchen kein POM für Ihre Datei, aber es wird auch nicht generiert. Wenn Sie also eines möchten, müssen Sie es separat hochladen.

Hier ist der Befehl:

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 Ein CLI-Wrapper um Sonatype Nexus REST.

Verwendungsbeispiel:

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

Die Konfiguration erfolgt über das .nexus_cli Datei.

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

Wenn Sie eine praktische Befehlszeilenschnittstelle oder python API benötigen, lesen Sie repositorytools

Mit diesem Befehl können Sie Artefakte in den Nexus hochladen

artifact upload foo-1.2.3.ext releases com.fooware

Damit es funktioniert, müssen Sie auch einige Umgebungsvariablen festlegen

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

Für neuere Versionen von Nexus OSS (> = 3.9.0)

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

Beispiel für die Versionen 3.9.0 bis 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

Sie können die Artefakte manuell hochladen, indem Sie im Nexus-Server auf die Schaltfläche Artefakte hochladen klicken und die erforderlichen GAV-Eigenschaften für das Hochladen angeben (dies ist im Allgemeinen die Dateistruktur zum Speichern des Artefakts).

0
jijendiran