如何将JCenter工件迁移到Sonatype Maven存储库?



JCenter Maven存储库将在一个月内关闭。

https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/?utm_source=mkto& utm_medium = email& utm_campaign = bintray-sunset& utm_content =全球- 02 - 2021

我如何在所有工件被删除之前将其迁移到Sonatype。

我已经用多个步骤解决了这个问题:

  • 首先,我编写了一个Java程序,从我的JCenter帐户下载所有的工件。然后我用Maven插件写了一个Gradle脚本。该脚本使用archiveBaseName、版本和工件的目录作为参数。脚本和maven插件添加了所有缺失的东西,比如PGP签名。然后我编写了一个Java程序,迭代下载的工件(或其中的一部分),并使用参数archiveBaseName, version和循环中的工件目录调用Gradle脚本。
  • 在Sonatype GUI上部署上传的文件。一次多个版本。

我使用的以下代码片段将无法开箱即用,因为它使用了内部私有API。但它可以作为一个起点。当然,您需要一个sonatype帐户和一个gpg环文件。秘密属性保存在gradle.properties文件中。您还需要自定义公司在所有3个文件中使用的组名。

下载

package tool;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import com.inet.lib.util.IOFunctions;
public class DownloadJCenter {
// this path will be cut on save
private static String basePath;
private static File   root;
public static void main( String[] args ) throws IOException {
basePath = "/";
URL startURL = new URL( "https://jcenter.bintray.com/com/company/" );
root = new File( "jcenter" );
load( startURL );
}
/**
* Load the URL iterative
* 
* @param parent the URL to load
* @throws IOException if any error occur
*/
static void load( @Nonnull URL parent ) throws IOException {
System.err.println( parent );
InputStream input = IOFunctions.openStreamSupportingRedirect( parent, 5000 );
String content = IOFunctions.readString( input, StandardCharsets.UTF_8 );
List<URL> urls = extractUrls( parent, content );
for( URL url : urls ) {
String path = url.getPath();
if( path.endsWith( "/" ) ) {
load( url );
} else {
input = IOFunctions.openStreamSupportingRedirect( url, 5000 );
byte[] bytes = IOFunctions.readBytes( input );
File file = new File( root, path.substring( basePath.length() ) );
file.getParentFile().mkdirs();
try (FileOutputStream fos = new FileOutputStream( file )) {
fos.write( bytes );
}
}
}
}
/**
* Extract the URLs from the content of page
* 
* @param parent the parent URL for relative URLs
* @param content the page content
* @return list of found URLs
* @throws IOException if any error occur
*/
@Nonnull
static List<URL> extractUrls( URL parent, @Nonnull String content ) throws IOException {
ArrayList<URL> result = new ArrayList<>();
int idx = 0;
while( true ) {
int idx1 = content.indexOf( "href="", idx );
if( idx1 < 0 ) {
break;
}
idx1 += 6;
int idx2 = content.indexOf( """, idx1 );
String urlStr = content.substring( idx1, idx2 );
if( !urlStr.startsWith( ".." ) ) {
result.add( new URL( parent, urlStr ) );
}
idx = idx2;
}
return result;
}
}

Gradle发射器

package tool;
import java.io.File;
import java.io.IOException;
import java.lang.ProcessBuilder.Redirect;
import java.util.ArrayList;
import java.util.HashMap;
import com.inet.error.ErrorCode;
import com.inet.lib.util.IOFunctions;
import com.inet.shared.utils.Version;
/**
* Deploy to the Sonatype server.
*/
public class DeploySonatype {
private static final String gradle = "C:/Users/...../gradle-6.7.1/bin/gradle.bat";
public static void main( String[] args ) throws IOException {
File root = new File( "jcenter/com/company" );
for( File file : root.listFiles() ) {
if( file.isDirectory() ) {
String archivesBaseName = file.getName();
deployLibrary( archivesBaseName, file );
}
}
}
static void deployLibrary( String archivesBaseName, File libraryDir ) throws IOException {
HashMap<Version,File> versionDirs = new HashMap<>();
for( File file : libraryDir.listFiles() ) {
if( file.isDirectory() ) {
versionDirs.put( new Version( file.getName()), file );
}
}
ArrayList<Version> versions = new ArrayList( versionDirs.keySet() );
versions.sort( null );// old versions first
for( Version version : versions ) {
File dir = versionDirs.get( version );
deployVersion( archivesBaseName, version, dir );
}
}
static void deployVersion( String archivesBaseName, Version version, File dir ) throws IOException {
System.err.println( archivesBaseName + " " + version + " " + dir );
File script = IOFunctions.getFile( DeploySonatype.class.getResource( "deploy.gradle" ) );
IOFunctions.deleteDir( new File( script.getParent(), "build" ) ); // clean from previous run
ArrayList<String> command = new ArrayList<>();
command.add( gradle );
command.add( "-b" );
command.add( """ + script.getPath() + """ );
command.add( "--stacktrace" );
command.add( "-ParchivesBaseName=" + archivesBaseName );
command.add( "-Pversion=" + version );
command.add( "-PartifactDir=" + dir.getAbsolutePath() );
command.add( "uploadArchives" );
System.err.println( command );
ProcessBuilder processBuilder = new ProcessBuilder( command );
processBuilder.redirectOutput( Redirect.INHERIT );
processBuilder.redirectError( Redirect.INHERIT );
processBuilder.environment().put( "JAVA_HOME", System.getProperty( "java.home" ) );
Process start = processBuilder.start();
try {
int exitValue = start.waitFor();
if( exitValue != 0 ) {
throw new IOException( "Exit Value: " + exitValue );
}
} catch( InterruptedException ex ) {
ErrorCode.throwAny( ex );
}
}
}

deploy.gradle

/****************************************
* Deploy to Maven
****************************************/
apply plugin: 'maven'
apply plugin: 'signing'
group = 'com.company'
println archivesBaseName + "/" + version + "  -> " + artifactDir // come from Java as parameter
task copyArtifact(type: Copy) {
from file( artifactDir )
into file("$buildDir/artifacts" )
}
task setupArchives {
dependsOn copyArtifact
doLast {
artifacts {
fileTree( dir: file( "$buildDir/artifacts" ) ).each {
archives file: it
println "t" + it
}
}
signing {
if (project.hasProperty("signing.keyId") ){
sign configurations.archives
}
}
}
}
uploadArchives {
dependsOn setupArchives
repositories {
mavenDeployer {
beforeDeployment { MavenDeployment deployment ->
signing {
fileTree( dir: file( "$buildDir/artifacts" ) ).each {
sign it
println "sign: " + it
}
}
}
if (project.hasProperty("ossrhUsername") ){
repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
authentication(userName: project["ossrhUsername"], password: project["ossrhPassword"])
}
}
}
}
}

最新更新