Передать артефакты на Нексус, без Мэйвен



У меня есть проект не Java, который создает версионный артефакт сборки, и я хочу загрузить его в репозиторий Nexus. Поскольку проект не является Java, он не использует Maven для сборки. И я бы предпочел не вводить файлы Maven/POM только для того, чтобы получить файлы в Nexus.



ссылки в блогах на Nexus REST API все заканчиваются на стене входа, без ссылки" создать пользователя", которую я вижу.



Итак, каков наилучший (или любой разумный) способ загрузки артефактов сборки в Nexus репозиторий без Maven? "bash + curl" было бы здорово, или даже скрипт Python.

1267   11  

11 ответов:

вы рассматриваете возможность использования командной строки Maven для загрузки файлов?

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

это автоматически создаст Maven POM для артефакта.

обновление

в следующей статье Sonatype говорится, что плагин Maven" deploy-file " является самым простым решением, но он также предоставляет некоторые примеры использования завиток:

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

С помощью 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

вы можете увидеть, что означают параметры здесь: https://support.sonatype.com/entries/22189106-How-can-I-programatically-upload-an-artifact-into-Nexus-

чтобы сделать разрешения для этой работы, я создал новую роль в графическом интерфейсе администратора и добавил две привилегии к этой роли: загрузка артефакта и загрузка артефакта. Стандартный " РЕПО: все репозитории Maven (полный контроль)"-роли недостаточно. Вы не найдете этого в остальном Документация API, которая поставляется в комплекте с сервером Nexus, поэтому эти параметры могут измениться в будущем.

On проблема Sonatype JIRA, было упомянуто, что они "собираются пересмотреть REST API (и то, как создается его документация) в предстоящем выпуске, скорее всего, в конце этого года".

вы можете абсолютно сделайте это, не используя ничего Maven связанных. Лично я использую HttpClient, который Нин (В1.8.16, чтобы поддержать java6).

по какой-то причине Sonatype делает это невероятно трудность выяснить, что правильные URL-адреса, заголовки и полезные нагрузки должны быть; и мне пришлось нюхать трафик и догадываться... Есть некоторые еле-еле полезные блоги/документация есть, но она либо не имеет отношения к oss.sonatype.org, или он основан на XML (и я узнал, что он даже не работает). Дерьмовая документация с их стороны, ИМХО, и, надеюсь, будущие искатели могут найти этот ответ полезным. Большое спасибо https://stackoverflow.com/a/33414423/2101812 за свой пост, так как это очень помогло.

если вы отпустите где-то кроме oss.sonatype.org, просто замените его на любой правильный хозяин.

вот код (CC0 licensed), который я написал для этого. Где profile ваш sonatype / nexus profileID (например,4364f3bbaf163) и repo (например,comdorkbox-1003) анализируются из ответа, когда вы загружаете свой первоначальный POM / Jar.

закрыть РЕПО:

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

продвижение РЕПО:

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

падение РЕПО:

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

удалить подпись какашек:

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

загрузка файлов:

    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:

как получить активность/статус РЕПО

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

нет необходимости использовать эти команды .. вы можете напрямую использовать веб-интерфейс nexus для загрузки своей банки с помощью параметров GAV.

enter image description here

вызовы, которые вам нужно сделать против Nexus, являются вызовами REST api.

Maven-nexus-plugin-это плагин Maven, который можно использовать для выполнения этих вызовов. Вы можете создать фиктивный pom с необходимыми свойствами и сделать эти вызовы через плагин Maven.

что-то типа:

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

считали, что:

  1. вы определили сервер в вашем~/.м2/настройки.xml с именем sonatype-nexus-staging с вашим пользователем sonatype и настройка пароля-вы, вероятно, уже сделали это, если вы развертываете моментальные снимки. Но вы можете найти дополнительную информацию здесь.
  2. локальные параметры.xml включает в себя Плагины nexus, как указано здесь.
  3. пом.xml, находящийся в вашем текущем каталоге, имеет правильные координаты Maven в своем определении. Если нет, можно указать groupId, artifactId и version в командной строке.
  4. - Dauto=true отключится интерактивные подсказки, чтобы вы могли написать это.

в конечном счете, все это делает создание вызовов REST в Nexus. Существует полный Nexus REST api, но мне не повезло найти документацию для него, которая не находится за платной стеной. Вы можете включить режим отладки для плагина выше и выяснить это, однако, используя -Dnexus.verboseDebug=true -X.

вы также можете теоретически войти в пользовательский интерфейс, включить панель Firebug Net и следить за сообщениями /service и вывести путь там же.

для тех, кому это нужно в Java, используя 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-это трудный путь. Если вы не хотите использовать maven (например : не разрешено)

посмотри Айви:

другой вариант gradle : http://www.gradle.org/docs/current/userguide/artifact_management.html#N14566

в ruby https://github.com/RiotGames/nexus_cli оболочка CLI вокруг вызовов Sonatype Nexus REST.

вы также можете использовать метод прямого развертывания с помощью curl. Вам не нужен pom для вашего файла, но он также не будет сгенерирован, поэтому, если вы хотите его, вам придется загрузить его отдельно.

вот команды:

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

Если вам нужен удобный интерфейс командной строки или Python API, то посмотри repositorytools

вместо этого можно использовать curl.

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

Comments

    Ничего не найдено.