Maven olmadan yapıları Nexus'a yükleyin


102

Sürümü belirlenmiş bir yapı yapısı üreten Java dışı bir projem var ve bunu bir Nexus deposuna yüklemek istiyorum. Proje Java olmadığı için, derlemeler için Maven kullanmaz. Ve sadece Nexus'a dosya almak için Maven / POM dosyalarını tanıtmamayı tercih ederim.

Bloglardaki Nexus REST API bağlantılarının tümü, görebildiğim hiçbir "kullanıcı oluştur" bağlantısı olmadan bir oturum açma duvarında sona eriyor.

Öyleyse, derleme yapılarını Maven'siz bir Nexus havuzuna yüklemenin en iyi (veya herhangi bir makul) yolu nedir? "bash + curl" harika olurdu, hatta bir Python betiği.


Not, ~ / .m2 içinde uygun sunucular ve kimlik doğrulaması tanımlanmış bir settings.xml'ye sahip olduğunuzdan emin olun.
Adam Vandenberg

Yanıtlar:


98

Dosyaları yüklemek için Maven komut satırını kullanmayı düşünüyor musunuz?

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

Bu, artefakt için otomatik olarak Maven POM'u oluşturacaktır.

Güncelleme

Aşağıdaki Sonatype makalesi "deploy-file" maven eklentisinin en kolay çözüm olduğunu belirtir, ancak curl kullanarak bazı örnekler de sağlar:

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


Keşke bu, dosyaları doğrudan bu zip içinden indirmemize izin verse, ancak bu şekilde yüklerseniz bu mümkün olmaz.
sorin

@sorin Maven kullanarak bir zip içinden dosya indirmek mümkün değildir. Bu alışılmadık bir gereklilik ve bunu yapabileceğini bildiğim tek bağımlılık yöneticisi sarmaşık (ve bu basit değil) aşağıdaki örneğe bakın: stackoverflow.com/questions/3445696/…
Mark O'Connor

Nexus'u her şeyi daha basit hale getirmek için kurdum, ama bu da ne? .. Ya bağımlılıkları hakkında bilgi sahibi olmadan ev yapımı bir JAR'ım varsa? IDE'm * .pom eksikliğinden şikayet etmeye devam ediyor. Nexus'un bunu benim için hallettiğini umuyordum, ama HAYIR ...
vintproykt

66

Curl kullanma:

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

Parametrelerin ne anlama geldiğini burada görebilirsiniz: https://support.sonatype.com/entries/22189106-How-can-I-programatically-upload-an-artifact-into-Nexus-

Bu işe yönelik izinleri yapmak için, yönetici GUI'sinde yeni bir rol oluşturdum ve bu role iki ayrıcalık ekledim: Yapı İndirme ve Yapı Yükleme. Standart "Depo: Tüm Maven Depoları (Tam Kontrol)" - rol yeterli değildir. Bunu Nexus sunucusuyla birlikte gelen REST API belgelerinde bulamazsınız, bu nedenle bu parametreler gelecekte değişebilir.

On bir Sonatype JIRA sorunu , bunların "büyük olasılıkla daha sonra bu yıl, daha sonraki bir sürümde DİNLENME API (ve 's belgelerine oluşturulur yolu) elden gidiyor" diye bahsedilmişti.


Diyelim ki Jenkins'ten yayınlıyoruz ve yalnızca derleme kullanıcılarının Nexus'ta yayınlamasına izin veriyoruz, düz parola sorununu nasıl yönetiyorsunuz? Jenkins'in yükleme için bir eklentisi var mı, böylece Jenkins kimlik bilgilerini kullanabiliriz?
Jirong Hu

8

Bu komutları kullanmanıza gerek yok .. JAR'ınızı GAV parametrelerini kullanarak yüklemek için doğrudan nexus web arayüzünü kullanabilirsiniz.

görüntü açıklamasını buraya girin

Bu yüzden çok basit.


24
Bir GUI yardımcı olmuyor; Derleme işleminin bir parçası olarak kullanılan bir komut satırı komut dosyası aracılığıyla karşıya yükleyebilmem gerekiyor.
Adam Vandenberg

Peki, bir HTTP POST isteğine dönüşüyor, sence de öyle değil mi?
Yngve Sneen Lindal

5
@YngveSneenLindal Elbette, ancak bu POST argümanlarının herkese açık olarak kullanılacak iyi tanımlanmış bir API olduğu anlamına gelmez.
Ken Williams

@KenWilliams Tabii, bunu da iddia etmedim. Ama işe yarayacaklar ve bir çözümü temsil edecekler, benim açımdan bu.
Yngve Sneen Lindal

En azından, Sonatype Nexus ™ 2.11.1-01 için kullanıcıya ayrıcalık vermem gerekiyordu Artifact Upload. Maalesef, belgelerde bundan bahseden hiçbir şey bulamadım ... (Düzenleme: Görüyorum, Ed bunu zaten belirtmiştim )
Alberto

8

Bunu KESİNLİKLE MAVEN ile ilgili herhangi bir şey kullanmadan yapabilirsiniz. Ben şahsen NING HttpClient (v1.8.16, java6'yı desteklemek için) kullanıyorum.

Her ne sebeple olursa olsun, Sonatype , doğru URL'lerin, başlıkların ve yüklerin ne olması gerektiğini anlamayı inanılmaz derecede zorlaştırır; ve trafiği koklamak ve tahmin etmek zorunda kaldım ... Orada zar zor kullanışlı bazı bloglar / belgeler var, ancak ya alakasız oss.sonatype.orgya da XML tabanlı (ve işe yaramadığını öğrendim). Kendi adına saçma belgeler, IMHO ve umarım gelecek arayanlar bu cevabı yararlı bulabilirler. Çok yardımcı olduğu için gönderileri için https://stackoverflow.com/a/33414423/2101812'ye çok teşekkürler .

Başka bir yerde yayınlarsanız oss.sonatype.org, onu doğru ana bilgisayarla değiştirin.

İşte bunu başarmak için yazdığım (CC0 lisanslı) kod. Nerede profilesenin sonatype / nexus profileID (gibi olan 4364f3bbaf163) ve repo(gibi comdorkbox-1003) Açılış POM / Jar yüklemek yanıttan ayrıştırılır.

Depoyu kapat:

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

Depoyu tanıtın:

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

Depo bırak:

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

İmza türlerini silin:

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

Dosya yüklemeleri:

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

DÜZENLEME1:

Depo için aktivite / durum nasıl alınır

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

6

Nexus'a karşı yapmanız gereken çağrılar REST api çağrılarıdır.

Maven-nexus-eklentisi, bu aramaları yapmak için kullanabileceğiniz bir Maven eklentisidir. Gerekli özelliklere sahip bir sahte pom oluşturabilir ve bu aramaları Maven eklentisi aracılığıyla yapabilirsiniz.

Gibi bir şey:

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

Varsayılan şeyler:

  1. ~ / .M2 / settings.xml adında sonatype-nexus-evreleme adında bir sunucu tanımladınız ve sonatip kullanıcınız ve parola ayarladınız - anlık görüntüleri dağıtıyorsanız muhtemelen bunu zaten yapmış olacaksınız. Ancak burada daha fazla bilgi bulabilirsiniz .
  2. Yerel settings.xml dosyanız, burada belirtilen nexus eklentilerini içerir .
  3. Geçerli dizininizde bulunan pom.xml, tanımında doğru Maven koordinatlarına sahiptir. Değilse, komut satırında groupId, artifactId ve sürümü belirtebilirsiniz.
  4. -Dauto = true, etkileşimli istemleri kapatır, böylece bunu komut dosyası edebilirsiniz.

Sonuçta, tüm bunlar Nexus'a REST çağrıları oluşturmaktır. Tam bir Nexus REST api var, ancak bunun için bir ödeme duvarının arkasında olmayan belgeleri bulma konusunda çok az şansım oldu. Yukarıdaki eklenti için hata ayıklama modunu açabilir ve bunu kullanarak anlayabilirsiniz -Dnexus.verboseDebug=true -X.

Ayrıca teorik olarak kullanıcı arayüzüne girebilir, Firebug Net panelini açabilir ve POST'ları izleyebilir / servis edebilir ve orada da bir yol tespit edebilirsiniz.


3

apache httpcomponents 4.0 kullanarak Java'da ihtiyaç duyanlar için:

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

ilk gönderi. Java için higlighting eklemeye çalıştım ama anlayamadım.
McMosfet

3

Ruby'de https://github.com/RiotGames/nexus_cli Sonatype Nexus REST çağrılarının etrafında bir CLI sarmalayıcı.

Kullanım Örneği:

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

Yapılandırma .nexus_clidosya üzerinden yapılır .

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

2

Curl kullanarak doğrudan dağıtım yöntemini de kullanabilirsiniz. Dosyanız için bir pom'a ihtiyacınız yok, ancak aynı zamanda oluşturulmayacak, bu yüzden isterseniz, ayrı olarak yüklemeniz gerekecek.

İşte komut:

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

"eser" artefakt değil
Ram

1

Kullanışlı bir komut satırı arayüzüne veya python API'ye ihtiyacınız varsa, depo araçlarına bakın

Bunu kullanarak, eseri bağlantı noktasına komutla yükleyebilirsiniz.

artifact upload foo-1.2.3.ext releases com.fooware

Çalışması için bazı ortam değişkenlerini de ayarlamanız gerekecek

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

0

Nexus sunucusundaki yapıları yükle düğmesine tıklayarak yapıları manuel olarak yükleyebilir ve yükleme için gerekli GAV özelliklerini sağlayabilirsiniz (genellikle yapıyı depolamak için dosya yapısıdır)


0

Nexus OSS'nin son sürümleri için (> = 3.9.0)

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

3.9.0 ila 3.13.0 sürümleri için örnek:

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 "raw.asset1=@test.txt;type=application/json" -F "raw.asset1.filename=test.txt"

-1

@Adam Vandenberg Nexus'a POST'a Java kodu için. https://github.com/manbalagan/nexusuploader

public class NexusRepository implements RepoTargetFactory {

    String DIRECTORY_KEY= "raw.directory";
    String ASSET_KEY= "raw.asset1";
    String FILENAME_KEY= "raw.asset1.filename";

    String repoUrl;
    String userName;
    String password;

    @Override
    public void setRepoConfigurations(String repoUrl, String userName, String password) {
        this.repoUrl = repoUrl;
        this.userName = userName;
        this.password = password;
    }

    public String pushToRepository() {
        HttpClient httpclient = HttpClientBuilder.create().build();
        HttpPost postRequest = new HttpPost(repoUrl) ;
        String auth = userName + ":" + password;
        byte[] encodedAuth = Base64.encodeBase64(
                auth.getBytes(StandardCharsets.ISO_8859_1));
        String authHeader = "Basic " + new String(encodedAuth);
        postRequest.setHeader(HttpHeaders.AUTHORIZATION, authHeader);
        try
        {
            byte[] packageBytes = "Hello. This is my file content".getBytes();
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
            InputStream packageStream = new ByteArrayInputStream(packageBytes);
            InputStreamBody inputStreamBody = new InputStreamBody(packageStream, ContentType.APPLICATION_OCTET_STREAM);
            multipartEntityBuilder.addPart(DIRECTORY_KEY, new StringBody("DIRECTORY"));
            multipartEntityBuilder.addPart(FILENAME_KEY, new StringBody("MyFile.txt"));
            multipartEntityBuilder.addPart(ASSET_KEY, inputStreamBody);
            HttpEntity entity = multipartEntityBuilder.build();
            postRequest.setEntity(entity); ;

            HttpResponse response = httpclient.execute(postRequest) ;
            if (response != null)
            {
                System.out.println(response.getStatusLine().getStatusCode());
            }
        }
        catch (Exception ex)
        {
            ex.printStackTrace() ;
        }
        return null;
    }

}

-2

Bunun yerine curl kullanabilirsiniz.

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

bu cevap doğru değil. Curl ile, groupId org / myorg olarak temsil edilmelidir (noktayı "." Bölü "/" ile değiştirin)
madduci
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.