Creating custom Maven resolver

Hi, I’m working on plugin that have custom Maven resolver pointing to private S3 buckets.
And it’s working fine, but when I want to use same resolver for ‘mave-publish’ plugin it won’t work.

Maybe I assemble resolver somehow wrong

Here how I did it:

Registering resolver:
class S3ResolverPlugin implements Plugin {

    public static final String PUBLISHS3BUILD__TASK_NAME = "publishS3Build"
    public static final String PUBLISHS3__TASK_NAME = "publishS3"
    public static final String COPYS3__TASK_NAME = "copyS3"

    @Override
    void apply(Project project) {
        S3ResolverHandler resolverHandler = new S3ResolverHandler(project)
        project.convention.plugins.customresolvers = resolverHandler
	}
}

Resolver class:

public class S3ResolverHandler {
    private static final Logger logger = Logging.getLogger(S3ResolverHandler.class)

    public static final String BUCKET_NAME_PROPERTY = "AWS_S3_BUCKET_NAME"
    public static final String ACCESS_KEY_PROPERTY = "AWS_ACCESSKEY"
    public static final String SECRET_KEY_PROPERTY = "AWS_SECRETKEY"

    public static final String BUCKET_NAME_RELEASE_PROPERTY = "AWS_S3_BUCKET_NAME_RELEASE";
    public static final String ACCESS_KEY_RELEASE_PROPERTY = "AWS_ACCESSKEY_RELEASE";
    public static final String SECRET_KEY_RELEASE_PROPERTY = "AWS_SECRETKEY_RELEASE";


    private Project project;

    public S3ResolverHandler(Project project) {
        this.project = project;
    }

    /**
     * Use Maven S3 Build (SNAPSHOT) bucket
     * @return
     */
    public MavenArtifactRepository mavenS3Build() {
        return mavenOnS3(BUCKET_NAME_PROPERTY, ACCESS_KEY_PROPERTY, SECRET_KEY_PROPERTY)
    }

    /**
     * Use Maven S3 Release bucket
     * @return
     */
    public MavenArtifactRepository mavenS3() {
        return mavenOnS3(BUCKET_NAME_RELEASE_PROPERTY, ACCESS_KEY_RELEASE_PROPERTY, SECRET_KEY_RELEASE_PROPERTY)
    }

    private MavenArtifactRepository mavenOnS3(String bucketNameProperty, String accessKeyProperty, String secretKeyProperty) {
        String awsUrl = "s3://" + util.getPropValue(bucketNameProperty);
        String awsAccessKey = util.getPropValue(accessKeyProperty);
        String awsSecretKey = util.getPropValue(secretKeyProperty);

        RepositoryHandler repositories = project.getRepositories()
        MavenArtifactRepository artifactRepository = repositories.maven {
            url awsUrl
            credentials(AwsCredentials) {
                accessKey awsAccessKey
                secretKey awsSecretKey
            }
        }
        logger.info("Use S3 bucket: {}", awsUrl)

        return artifactRepository
    }
}

How I’m using resolver, and it’s working fine:

repositories {
    mavenS3()
    mavenCentral()
}

And I want to reuse same mavenS3() resolver for publishing:

publishing {
    publications {
        mavenJava(MavenPublication) {
            artifactId packageName
            groupId 'com.xxxx.zzzz'
            version project.version
            artifact distZip
        }
    }

    repositories {
    	mavenS3()
    }
}

But It won’t work.
When I’m using mavenS3() resolver, publish task return that is UP-TO-DATE.
But with other mavenCentral() publishing is working fine.

Does someone have some suggestions?

If I use mavenCentral(), or mavenLocal() resolver for publishing, it work fine.

Gradle natively supports resolving from and publishing to S3. Curious why you would write a plugin for this?

Docs here: http://docs.gradle.org/current/userguide/dependency_management.html#sub:supported_transport_protocols

I’m using this approach because I’m using two sets of environment variables used in mavenS3() and mavenS3Build().
And I want to hide configuration/settings.

When I’m using mavenS3() resolver for downloading dependencies, everything is working well.
But when I want to use same resolver for publish task, then it won’t work.

publishing {
    repositories {
        mavenS3()
    }
}

If I’m using mavenCentral() resolver for publish, then publishing is working fine.

Is there any difference when using resolver in publishing?
Maybe I need to create resolver differently?

The internals of the maven publishing plugins are not intended to accept the same RepositoryHandler's. It’s mentioned here: https://docs.gradle.org/current/javadoc/org/gradle/api/publish/PublishingExtension.html#repositories(org.gradle.api.Action)

The DSL is the same but the internals are different.

Hi, thx for clear that out!

Is there a way/idea how to create custom repository handler, which can be accepted by maven-publish plugin?

One way I can think of is to call configure on a closure which has the repository details. Your plugin would be supplying a closure with the repository details rather than a RepositoryHandler

publishing {

  repositories {
    configure(rootProject.ext.releaseRepos)
  }

  publications {
    mavenJava(MavenPublication) {
......

Your plugin would do something like:

project.ext {
    releaseRepos = {
        if (isSnapshotBuild) {
            maven {
                name 'jfrogOss'
                url "${artifactRepoBase}/${repoPrefix}-${type}-local"
                credentials {
                    username = "${login.username}"
                    password = "${login.password}"
                }
            }
        }
    }
}

Hi, thx for the help.

I build solution based on your suggestion:

private Closure uploadMavenS3() {
    def closure = {
        maven {
            url awsUrl
            credentials(AwsCredentials) {
                accessKey awsAccessKey
                secretKey awsSecretKey
            }
        }
    }

    return closure
}

And I can use is as:

publishing {
        repositories {
            configure(uploadMavenS3())
        }
    }