Mavenを使用せずにアーティファクトをNexusにアップロードする


102

バージョン化されたビルドアーティファクトを生成する非Javaプロジェクトがあり、これをNexusリポジトリにアップロードしたい。プロジェクトはJavaではないため、ビルドにMavenを使用しません。また、ファイルをNexusに取り込むためだけにMaven / POMファイルを導入したくない。

ブログのNexus REST APIへのリンクはすべてサインインウォールで終わり、「ユーザーの作成」リンクは表示されません。

それでは、MavenなしでビルドアーティファクトをNexusリポジトリにアップロードするための最良の(または妥当な)方法は何ですか?"bash + curl"は素晴らしい、あるいはPythonスクリプトです。


適切なサーバーと認証が定義された〜/ .m2にsettings.xmlがあることを確認してください。
Adam Vandenberg、

回答:


98

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記事では、「deploy-file」mavenプラグインが最も簡単なソリューションであると述べていますが、curlを使用した例もいくつか示しています。

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


これだけで、このzip内から直接ファイルをダウンロードできるようになりますが、このようにアップロードした場合、それは不可能であるようです。
ソリン2015年

@sorin Mavenを使用してzip内からファイルをダウンロードすることはできません。それは珍しい要件だと私はそれを行うことができます知っている唯一の依存性マネージャはツタである(そして、それは簡単ではありません)、次の例を参照してください。stackoverflow.com/questions/3445696/...
マーク・オコナー

すべてを簡単にするためにNexusをインストールしましたが、これは何ですか?依存関係を知らない自家製のJARがあるとどうなりますか?IDEが* .pomの欠落について文句を言い続けます。ネクサスがそれをすでに処理してくれることを望みましたが、NOOOOO sh ...
vintproykt

66

カールを使用する:

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-

この作業のアクセス許可を作成するために、管理GUIで新しいロールを作成し、そのロールにArtifact DownloadとArtifact Uploadの2つの特権を追加しました。標準の「リポジトリ:すべてのMavenリポジトリ(フルコントロール)」の役割では不十分です。これは、NexusサーバーにバンドルされているREST APIドキュメントには記載されていないため、これらのパラメーターは将来変更される可能性があります。

Sonatype JIRAの問題、それは彼らが「最も可能性が高い今年後半に、今後のリリースでRESTのAPI(およびそれのドキュメントが生成される方法)をオーバーホールしようとしている」と述べました。


Jenkinsから公開し、ビルドユーザーにのみNexusへの公開を許可するとします。通常のパスワードの問題をどのように管理しますか?Jenkinsにはアップロード用のプラグインがあるので、Jenkinsの認証情報を使用できますか?
Jirong Hu 2016

8

これらのコマンドを使用する必要はありません。GAVパラメータを使用してJARをアップロードするために、Nexus Webインターフェイスを直接使用できます。

ここに画像の説明を入力してください

とても簡単です。


24
GUIは役に立ちません。ビルドプロセスの一部として使用されるコマンドラインスクリプトを介してアップロードできる必要があります。
Adam Vandenberg、

まあ、それはHTTP POSTリクエストに変換されますね。
Yngve Sneen Lindal 2013

5
@YngveSneenLindalもちろん、それらのPOST引数がパブリックに使用するための明確に定義されたAPIであることを意味するものではありません。
ケンウィリアムズ

@KenWilliamsもちろん、私もそれを主張しなかった。しかし、それらは機能し、解決策を表すでしょう、それが私のポイントです。
Yngve Sneen Lindal 2014

少なくとも、私たちのSonatype Nexus™2.11.1-01では、ユーザーに特権を付与する必要がありましたArtifact Upload。残念ながら、これについて言及しているドキュメントには何も見つかりませんでした...(編集:なるほど、Ed私はすでにこれを指摘しています
Alberto

8

MAVENに関連するものを使用せずに、これを完全に行うことができます。私は個人的にNING HttpClient(v1.8.16、java6をサポート)を使用しています。

理由が何であれ、Sonatypeは、正しいURL、ヘッダー、およびペイロードが何であると想定されているかを理解することを非常に困難にします。そして、私はトラフィックを推測して推測しなければなりませんでした ...そこにはかろうじて有用なブログ/ドキュメントがいくつかありますが、それはに無関係であるかoss.sonatype.org、またはXMLベースです(そして私はそれがうまくいかないこともわかりました)。私の側のクラップ文書、私見、そしてうまくいけば、将来の探求者はこの答えが役に立つと思うでしょう。https://stackoverflow.com/a/33414423/2101812の投稿に感謝します

以外の場所でリリースする場合oss.sonatype.orgは、正しいホストが何であるかに置き換えてください。

これを実現するために私が書いた(CC0ライセンス)コードです。どこにprofileあなたのsonatype /ネクサスprofileIDを(のようなさ4364f3bbaf163)とrepo(などはcomdorkbox-1003)あなたが最初のPOM /ジャーをアップロード応答から解析されています。

リポジトリを閉じる:

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

編集1:

リポジトリのアクティビティ/ステータスを取得する方法

/**
 * 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に対して行う必要がある呼び出しはREST API呼び出しです。

maven-nexus-pluginは、これらの呼び出しを行うために使用できるMavenプラグインです。必要なプロパティを備えたダミーのpomを作成し、Mavenプラグインを介してそれらの呼び出しを行うことができます。

何かのようなもの:

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

想定されるもの:

  1. 〜/ .m2 / settings.xmlにsonatype-nexus-stagingという名前のサーバーを定義し、sonatypeユーザーとパスワードを設定しました。スナップショットをデプロイする場合は、すでにこれを行っているでしょう。しかし、あなたはここでより多くの情報を見つけることができます。
  2. ローカルのsettings.xmlには、ここで指定されているネクサスプラグインが含まれています
  3. 現在のディレクトリにあるpom.xmlの定義には、正しいMaven座標が含まれています。そうでない場合は、コマンドラインでgroupId、artifactId、およびversionを指定できます。
  4. -Dauto = trueは対話型プロンプトをオフにするため、これをスクリプト化できます。

最終的に、これが行っているのは、NexusへのREST呼び出しを作成することだけです。完全なNexus REST APIがありますが、ペイウォールの背後にあるものではない、そのためのドキュメントを見つけることがほとんどできませんでした。上記のプラグインのデバッグモードをオンにして、を使用してそれを理解することができます-Dnexus.verboseDebug=true -X

理論的にはUIに移動し、Firebug Netパネルをオンにして、/ service POSTを監視し、そこでパスを推定することもできます。


3

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

最初の投稿。Javaにハイライトを追加しようとしましたが、うまくいきませんでした。
McMosfet、2015年

3

ruby内https://github.com/RiotGames/nexus_cli Sonatype Nexus REST呼び出しのCLIラッパー。

使用例:

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

設定は.nexus_cliファイルを介して行われます。

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

2

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

アーティファクトではなく「アーティファクト」
Ram

1

便利なコマンドラインインターフェースまたはPython APIが必要な場合は、repositorytoolsをご覧ください。

それを使用して、コマンドでアーティファクトをネクサスにアップロードできます

artifact upload foo-1.2.3.ext releases com.fooware

それを機能させるには、いくつかの環境変数も設定する必要があります

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

0

Nexusサーバーのアーティファクトのアップロードボタンをクリックしてアーティファクトを手動でアップロードし、アップロードに必要なGAVプロパティを提供できます(通常、アーティファクトを保存するためのファイル構造です)


0

Nexus OSSの最新バージョン(> = 3.9.0)

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

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

-1

@Adam Vandenberg Javaコードの場合はNexusにPOSTします。 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

代わりに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

この答えは正しくありません。curlでは、groupIdはorg / myorgとして表す必要があります(ドット「。」をスラッシュ「/」に
置き換えます
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.