Search code examples
javagradleartifactorygradle-plugin

Artifactory + Custom Gradle Plugin Programmatically (2022)


I'm trying to create a custom gradle plugin (100% java) which will automatically configure Artifactory, avoiding the need of the following DSL:

artifactory {
contextUrl = "${artifactory_contextUrl}"   //The base Artifactory URL if not overridden by the publisher/resolver
publish {
    repository {
        contextUrl = "${artifactory_contextUrl}"
        repoKey = 'android-dev'
        username = "${artifactory_user}"
        password = "${artifactory_password}"
        maven = true

    }
}
resolve {
    repository {
        contextUrl = "${artifactory_contextUrl}"
        repoKey = 'android-dev-distributions'
        username = "${artifactory_user}"
        password = "${artifactory_password}"
        maven = true

    }
}
}

I'm trying to re-create @agrosner own solution (from https://stackoverflow.com/a/25669431/1880280) but I'm missing "ArtifactoryAction". I can't find it anywhere.

The nonworking version posted by @agrosner is the following code:

// Set up plugins so we never need to add them to a build.gradle
    project.getPlugins().apply(MAVEN);
    project.getPlugins().apply(ARTIFACTORY);
    project.setGroup(GROUP);

    // Add Artifactory repo to the repositories
    project.getRepositories().maven(new ArtifactoryAction(contextUrl + ARTIFACTORY_REPO_ENDPOINT, user, pass));

    // We will define the plugin convention here so all of our libraries do not need to
    // declare the artifactory closure manually
    ArtifactoryPluginConvention pluginConvention =
            ArtifactoryPluginUtil.getArtifactoryConvention(project);
    pluginConvention.setContextUrl(contextUrl);

    PublisherConfig publisherConfig = new PublisherConfig(pluginConvention);
    publisherConfig.setContextUrl(contextUrl);
    pluginConvention.setPublisherConfig(publisherConfig);

    // Use reflection to access private field
    PublisherConfig.Repository repository = null;

    Field[] fields = PublisherConfig.class.getDeclaredFields();
    for(Field field : fields) {
        if(field.getName().equalsIgnoreCase("repository")) {
            try {
                field.setAccessible(true);
                repository = (PublisherConfig.Repository) field.get(publisherConfig);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    if(repository != null) {
        repository.setPassword(pass);
        repository.setUsername(user);
        repository.setRepoKey(PUBLISHER_REPO_KEY);
        repository.setMavenCompatible(true);
    }

    GradleArtifactoryClientConfigUpdater.update(pluginConvention.getClientConfig(), project.getRootProject());

Can anyone help with an updated 100% java version of this?

Additionally, how would be for the following DSL?

artifactory {
publish {
    repository {
        repoKey =  'default-gradle-dev-local' // The Artifactory repository key to publish to
        username = "${artifactory_user}" // The publisher user name
        password = "${artifactory_password}" // The publisher password
        maven       = true
    }
    defaults {
        publications('mavenJava')
        publishArtifacts = true
        publishPom = true
    }
}}

Thanks in advance

César

ps. The DSL version that was published at @agrosner question thread is not useful for me. I need a Java version.


Solution

  • For your first question related to ArtifactoryAction: this is neither Gradle API nor Artifactory plugin related api, but most probably a custom class that the response author has implemented himself, as a shortcut to declare his custom Artifactory maven repo.

    See this API, used to declare maven repositories :

    MavenArtifactRepository maven​(Action<? super MavenArtifactRepository> action)
    

    So you can use:

    project.getRepositories().maven( mavenArtifactRepository -> {
         mavenArtifactRepository.setUrl(contextUrl + MAVEN_PUBLIC_REPO);
         mavenArtifactRepository.getCredentials().setUsername("user");
         mavenArtifactRepository.getCredentials().setPassword("password");
    });
    

    or wrap the action code into a custom implementation of Action<? super MavenArtifactRepository> :

    project.getRepositories().maven( new ArtifactoryAction(contextUrl + MAVEN_PUBLIC_REPO, "user", "password")        );
    
    [...]
    // custom action class, defined somewhere else
    class ArtifactoryAction implements Action<MavenArtifactRepository> {
        private final String url, userName, password;
    
        ArtifactoryAction(String url, String userName, String password) {
            this.url = url; this.userName = userName; this.password = password;
        }
    
        @Override
        public void execute(MavenArtifactRepository target) {
            target.setUrl(url);
            target.getCredentials().setUsername(userName);
            target.getCredentials().setPassword(password);
        }
    }
    

    For the other question with java translation of the artifactory { } DSL : see full example below with some inline comments. ( not tested but translated from my kotlin implementation which works fine)

    import org.gradle.api.Plugin;
    import org.gradle.api.Project;
    import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
    import org.jfrog.gradle.plugin.artifactory.ArtifactoryPlugin;
    import org.jfrog.gradle.plugin.artifactory.ArtifactoryPluginUtil;
    import org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention;
    import org.jfrog.gradle.plugin.artifactory.dsl.PublisherConfig;
    
    public class CustomArtifactoryPlugin implements Plugin<Project> {
    
        private static String MAVEN_PUBLIC_REPO = "/maven-public";
        private String contextUrl = "MY_CUSTOM_REPO_BASE_URL";
    
        @Override
        public void apply(Project project) {
    
            // Base gradle publishing plugin
            //  - maven plugin for pulishing java artefacts
            //  - ivy plugin if for publishing other type of artefacts: rpms, archives, ..
            project.getPluginManager().apply(MavenPublishPlugin.class);
            // project.getPluginManager().apply(IvyPublishPlugin.class);
    
            // Apply the Artifactory plugin
            project.getPluginManager().apply(ArtifactoryPlugin.class);
    
            // Add Artifactory repo to the repositories
            project.getRepositories().maven(new ArtifactoryAction(contextUrl + MAVEN_PUBLIC_REPO, "user", "password"));
    
            // Configure artifactory plugin - using 'withPlugin' ensures that plugin has already been applied
            project.getPluginManager().withPlugin("com.jfrog.artifactory", appliedPlugin -> {
                // artifactory {
                ArtifactoryPluginConvention pluginConvention = ArtifactoryPluginUtil.getArtifactoryConvention(project);
                //    contextUrl = "${contextUrl}"
                pluginConvention.setContextUrl(contextUrl);
                //    publish {
                PublisherConfig publisherConfig = new PublisherConfig(pluginConvention);
                pluginConvention.setPublisherConfig(publisherConfig);
                //      repository {
                pluginConvention.getPublisherConfig().repository(repository -> {
                    //      repoKey =  'default-gradle-dev-local'  ...
                    repository.setRepoKey("default-gradle-dev-local"); // The Artifactory repository key to publish to
                    repository.setUsername("${artifactory_user}"); // The publisher user name
                    repository.setPassword("${artifactory_password}"); // The publisher password
                    repository.setMavenCompatible(true);
                });
                //      defaults {
                pluginConvention.getPublisherConfig().defaults(artifactoryTask -> {
                    //      publications('mavenJava')
                    artifactoryTask.publications("mavenJava");
                    artifactoryTask.setPublishArtifacts("true");
                    artifactoryTask.setPublishPom("true");
                });
    
            });
        }
    
    }
    
    

    EDIT for the publication configuration, you can do as follows:

            // create maven publication
            project.getExtensions().configure(PublishingExtension.class, publishingExtension -> {
                publishingExtension.publications(publications -> {
                    publications.create("mavenPublication", MavenPublication.class, mavenPublication -> {
                        mavenPublication.setVersion("1.0.0");
                        mavenPublication.setGroupId("groupId");
                        mavenPublication.from(project.getComponents().findByName("java"));
                    });
                });
            });