Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a method to every `repositories` block, or every RepositoryHandler?

A large project with many developers and gradle projects uses a private maven repository for plugins, dependencies, and publication.

I would like to define a privateMaven() method, just like the built-in jcenter(), mavenCentral(), and google() methods. Currently we write a maven block anywhere we need to use the repository - repositories, publishing.repositories, pluginManagement.repositories, ...

repositories {
  maven {
    url "..."
    credentials { ... }
  }
}

which I would rather be

repositories {
  private()
}

This answer explains how to extend repositories and buildscript.repositories but it doesn't work for publishing.repositories because publishing is provided by a plugin and doesn't work for pluginManagement.repositories. Also I would also have to enumerate every repositories configuration and developers can't use privateMaven() in any block we don't extend.

Is there a way for an init script to add a method to every repositories block, or every RepositoryHandler?

like image 465
everett1992 Avatar asked Oct 15 '25 03:10

everett1992


2 Answers

Assuming you're using the maven-publish plugin, you can define an extension like so:

private.gradle

apply plugin: 'maven-publish'

publishing.repositories.ext.privateRepo = {
    publishing.repositories.maven {
        url "https://artifactory.website.com/private-repo"
        credentials {...}
    }
}

build.gradle

apply from: 'private.gradle' // or you can just include the script in here

afterEvaluate {
    publishing {
        publications {...}
        repositories {
            privateRepo()
        }
    }
}

You can also create a plugin if you'd like to distribute the script, the usage would remain exactly the same. https://guides.gradle.org/implementing-gradle-plugins/

PrivatePlugin.groovy

class PrivatePlugin implements Plugin<Project> {
    @Override
    void apply(Project project) {
        // check if the publishing extension exists first
        final publishing = project.extensions.findByType(PublishingExtension.class)
        if (publishing != null) {
            publishing.repositories.ext.privateRepo = {
                publishing.repositories.maven {
                    url "https://artifactory.website.com/private-repo"
                    credentials {...}
                }
            }
        }
    }
}

Just be sure that if you distribute it as a plugin that you don't ship it with the credentials hardcoded.

like image 78
Nathan Reline Avatar answered Oct 17 '25 17:10

Nathan Reline


My goal is that any repositories block can use privateMaven. I don't want to explicitly extend publishing.repositories.ext, repositories.ext, buildscript.repositories.ext. In addition to being tedious, if I miss one repositories or gradle adds a new repositories then privateMaven will not be available.

One solution which is close, but not perfect, was to create an extension on with a method that takes a reference to RepositoryHandler.

Any repository block and now use the extension as so

repositories {
  custom.privateMaven(it)
}
beforeSettings {
  extensions.create("custom", PrivateMavenExtension::class)
}
     
allprojects {
  extensions.create("custom", PrivateMavenExtension::class)
}

open class PrivateMavenExtension {
  fun privateMaven(handler: RepositoryHandler): MavenArtifactRepository {
    return handler.maven {
      // implementation
    }
  }
}

One major hurdle I haven't solved is that classes defined in an init.d script cannot be loaded in build.gradle. If PrivateMavenExtensions is defined in an init.d script I can't reference the extension in a type-safe way from a build.gradle.kts because the<PrivateMavenExtension>() cannot be resolved.

like image 35
everett1992 Avatar answered Oct 17 '25 19:10

everett1992



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!