clarityai-eng/codeartifact-gradle-plugin

Unable to get the plugin to work for repositories within a pluginManagement block

Opened this issue · 5 comments

As I don't see any pluginManagement in your README.md, I assume it's not supported.

Are you aware of any such limitation?

This is what I'm trying to do:

pluginManagement {
    repositories {
        maven {
            url = uri(
                "https://SCRUBBED.codeartifact.REGION.amazonaws.com/maven/SCRUBBED/"
            )
        }
    }
}

As I intend to publish gradle plugins to CodeArtifact, other projects need a way to consume said plugins...

This allowed me to add pluginManagement repositories support for CodeArtifact

@TypeChecked
class CodeArtifactPluginRepositoriesPlugin implements Plugin<Settings> {
    void apply(Settings settings) {
        def gradle = settings.getGradle()
        def pluginRepositories = settings.pluginManagement.repositories
        SharedFunctions.setupCodeartifactRepositoriesByUrl(gradle, pluginRepositories)
    }
}

It would be better if this could be baked into the library so that others can profit from it.

I don't have a PR because:

  • the setupCodeartifactRepositories() variant seems to be doing some magic that does not allow me to use @TypeChecked (so I had to comment it out entirely), and that capability (adding repository through a codeartifact{} block??) is not mentioned in the README.md.
  • a logger is not available when dealing with Settings (at least, none that I can find). So I had to use println instead to cover the Project and the Settings execution path in the shared configRepositories(RepositoryHandler repositories, Provider<CodeArtifactToken> serviceProvider) function.
@TypeChecked
class CodeArtifactRepositoriesPlugin implements Plugin<Project> {
    void apply(Project project) {
        def gradle = project.getGradle()

        //setupCodeartifactRepositories(project, serviceProvider) <-- magic
        SharedFunctions.setupCodeartifactRepositoriesByUrl(gradle, project.repositories)
    }
}

Other than that the SharedFunctions contains the functions required by both plugins

package ai.clarity.codeartifact

import groovy.transform.TypeChecked
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
import org.gradle.api.invocation.Gradle
import org.gradle.api.provider.Provider

@TypeChecked
class SharedFunctions {

    static Provider<CodeArtifactToken> codeArtifactTokenProviderFor(Gradle gradle) {
        return gradle
                .getSharedServices()
                .registerIfAbsent('codeartifact-token', CodeArtifactToken.class, {})
    }

    static void setupCodeartifactRepositoriesByUrl(Gradle gradle, RepositoryHandler repositories) {
        configRepositories(repositories, codeArtifactTokenProviderFor(gradle))
    }

    private static void configRepositories(RepositoryHandler repositories, Provider<CodeArtifactToken> serviceProvider) {
        ListIterator it = repositories.listIterator()
        while (it.hasNext()) {
            def artifactRepository = it.next()
            if (artifactRepository instanceof MavenArtifactRepository) {
                MavenArtifactRepository mavenRepo = (MavenArtifactRepository) artifactRepository;
                URI repoUri = mavenRepo.getUrl()
                if (isCodeArtifactUri(repoUri) && areCredentialsEmpty(mavenRepo)) {
                    String profile = getProfileFromUri(repoUri, getDefaultProfile())
                    //logger.info('Getting token for {} in profile {}', repoUri.toString(), profile)   <-- no logger for Settings
                    println("Getting token for $repoUri in profile $profile")
                    String token = serviceProvider.get().getToken(repoUri, profile)
                    mavenRepo.credentials({
                        it.username = 'aws'
                        it.password = token
                    })
                    mavenRepo.setUrl(removeProfile(repoUri))
                }
            }
        }
    }

    private static String getDefaultProfile() {
...
    }

    private static URI removeProfile(URI uri) {
...
    }

    private static boolean areCredentialsEmpty(MavenArtifactRepository mavenRepo) {
...
    }

    private static boolean isCodeArtifactUri(URI uri) {
...
    }

    private static String getProfileFromUri(URI uri, String defaultValue) {
...
    }
}

And the gradlePlugin block declares each of them separately

gradlePlugin {
    plugins {
        codeArtifactRepositories {
            id = 'ai.clarity.codeartifact.repositories'
            implementationClass = 'ai.clarity.codeartifact.CodeArtifactRepositoriesPlugin'
        }
        codeArtifactPluginRepositories {
            id = 'ai.clarity.codeartifact.pluginRepositories'
            implementationClass = 'ai.clarity.codeartifact.CodeArtifactPluginRepositoriesPlugin'
        }
    }
}

I'm going to submit a PR, with the smallest change possible, as I was unable to refactor effectively in the absence of type checking (some errors only show up at runtime, after publishing the plugin, making the refactoring experience hell).

Created a PR (#230). Keep what you like and throw the rest away.

Updated #230

Updated PR #230 hopefully for the last time.