バージョン付きビルドアーティファクトを生成するJava以外のプロジェクトがあり、これをNexusリポジトリにアップロードしたい。プロジェクトはJavaではないため、ビルドにMavenを使用しません。そして、ファイルをNexusに取り込むためだけにMaven/POMファイルを導入したくない。
ブログのNexus REST APIへのリンクはすべてサインインウォールになりますが、「ユーザーの作成」リンクは表示されません。
それでは、Mavenを使用せずにNexusリポジトリにビルドアーティファクトをアップロードする最良の(または合理的な)方法は何でしょうか? 「bash + curl」、またはPythonスクリプトも素晴らしいでしょう。
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を使用したいくつかの例も提供しています。
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-
この作業のアクセス許可を作成するために、管理GUIで新しいロールを作成し、そのロールに2つの特権を追加しました:アーティファクトのダウンロードとアーティファクトのアップロード。標準の「リポジトリ:すべてのMavenリポジトリ(フルコントロール)」-ロールでは不十分です。 NexusサーバーにバンドルされているREST APIドキュメントにはこれがありません。したがって、これらのパラメーターは将来変更される可能性があります。
Sonatype JIRAの問題 については、今後のリリースで「REST」API(およびドキュメントの生成方法)をオーバーホールする予定であり、おそらくこれ以降年"。
これらのコマンドを使用する必要はありません。GAVパラメーターを使用してJARをアップロードするには、nexus Webインターフェースを直接使用できます。
とても簡単です。
絶対に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/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に対して行う必要がある呼び出しは、REST api呼び出しです。
Maven-nexus-pluginは、これらの呼び出しを行うために使用できるMavenプラグインです。必要なプロパティを持つダミーのpomを作成し、Mavenプラグインを介してそれらの呼び出しを行うことができます。
何かのようなもの:
mvn -DserverAuthId=sonatype-nexus-staging -Dauto=true nexus:staging-close
想定されるもの:
最終的に、これはすべて、NexusへのREST呼び出しを作成することです。完全なNexus REST apiがありますが、ペイウォールの背後にないドキュメントを見つけることができませんでした。上記のプラグインのデバッグモードをオンにし、-Dnexus.verboseDebug=true -X
を使用してそれを把握できます。
また、理論的にはUIに移動してFirebug Netパネルをオンにし、/ service POSTを監視して、そこへのパスを推測することもできます。
apache httpcomponents 4.0を使用して、Javaで必要な場合:
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を使用して直接展開する方法も使用できます。ファイル用のPOMは必要ありませんが、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
In 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"
便利なコマンドラインインターフェイスまたは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
Nexus OSSの最新バージョン(> = 3.9.0)
バージョン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"
Nexusサーバーの[成果物のアップロード]ボタンをクリックして成果物を手動でアップロードし、アップロードに必要なGAVプロパティを提供できます(通常、成果物を保存するためのファイル構造です)