Skip to content

Conversation

ethankhall
Copy link
Contributor

This is a first pass at adding the ability to define a custom plugin portal.

I don't like the names of most of the classes, I would appreciate some suggestions to fix it. I also put some of it in it's own package, but that was just to help keep it separate, but I am more than happy to remove the package.

This still needs tests but I wanted to open the review now to get some early feedback.

@ldaley
Copy link
Contributor

ldaley commented Nov 18, 2016

I'm on my way back to AU. I'll look into this on my Monday. Thanks @ethankhall!

@ethankhall
Copy link
Contributor Author

Awesome! Let me know what you think. If this is the path we want to take I'll add some tests for it.

@ldaley
Copy link
Contributor

ldaley commented Nov 25, 2016

@ethankhall I think this is looking good. I've left some requests in there. The main theme is that we want to reduce the user implementable types, but add more type safety and avenues for evolution.

We also need to come up with a better name for this than “custom” :\ @oehme @eljobe any ideas?

@ethankhall
Copy link
Contributor Author

@alkemist I didn't see any comments on the PR.

@oehme
Copy link
Contributor

oehme commented Nov 25, 2016

The current implementation is probably not what you want. It uses the (otherwise unused) code path for "isolated" plugins, which means that plugins resolved from such a custom repo will be isolated and unable to see any other plugins. You'll want to use the "legacy" (misleading name) code path instead.

A better name/DSL for this could be

pluginRepositories {
  ruleBased {
    description = "The Foobar plugins"
    artifactRepositories {
      maven {
        url = 'foobar'
      }
    }
    pluginResolution { plugin, target ->
      if (plugin.id == "foobar") {
        target.useModule("com.foo:bar:${plugin.version}")
      }
    }
  }
}

@ethankhall
Copy link
Contributor Author

Using the Isolated code path can you access plugins in the same jar / dependencies of the plugin? That would solve an issue I have with plugins using different library versions that aren't compatible nicely.

Can plugins using the plugin portal configure other plugins? It sounds like not.

@oehme
Copy link
Contributor

oehme commented Nov 26, 2016

Plugins using the plugins block work just like when you use the buildscript block. They can configure other plugins etc. This custom one should be no exception, otherwise it would confuse users.

We could make the new isolated behavior opt-in of course, by offering another method on the target in the dsl I proposed above.

@ethankhall
Copy link
Contributor Author

Sounds good. I'll work on making those changes. Will this api be avaliable via an Init Script / what would the api to access it look like?

@oehme
Copy link
Contributor

oehme commented Nov 28, 2016

There is currently no pluginRepositories API in init scripts. I think it makes perfect sense to add it. @alkemist had some concerns though that we might want two different concepts:

  • an init script needs some plugins itself and the repository should only be used for that init script
  • an init script adds plugin repositories to the build that it applies to

@ethankhall
Copy link
Contributor Author

Alrighty, I'll want to add some API to configure this as part of an init script, but i'll work on the bit make the API better first.

@ethankhall
Copy link
Contributor Author

@oehme I've done the API changes that you requested. Let me know if that's what your thinking.

@ethankhall
Copy link
Contributor Author

@alkemist @oehme, how do you want to expose this in init scripts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a lot of unnecessary code churn here, probably caused by a rename refactoring. Could you revert that and use the interface type where applicable?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name is missing a word I think, maybe "Handler"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not introduce another type, but just change/rename the existing BackedByArtifactRepository.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need a new type here, let's use RepositoryHandler.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other Gradle APIs don't define new interfaces, but instead provide a single parameter object and use an Action. I think we should stick with that pattern to keep it consistent.

@oehme
Copy link
Contributor

oehme commented Nov 29, 2016

@ethankhall Let's tackle init scripts in another PR. I think the most straightforward thing would be to allow the pluginRepositories {} block in init scripts and let it mean "add those repositories to the list of plugin repositories of the build I'm applied to`. That's probably the most common use case which should have a convenient syntax. @alkemist what do you think?

ldaley
ldaley previously requested changes Nov 30, 2016
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should take a structured object, and return some kind of result object. Something like this …

CustomPluginResolutionResult resolvePlugin(PluginRequest plugin, CustomPluginResolutionResultFactory resultFactory)

CustomPluginResolutionResult should be a sealed type hierarchy, with two subtypes: ResolvedCustomPluginResolutionResult and UnresolvedCustomPluginResolutionResult. These latter two should be final and all should have package scoped constructors.

CustomPluginResolutionResultFactory should have methods that create instances of these two types. e.g.

interface CustomPluginResolutionResultFactory {
    ResolvedCustomPluginResolutionResultFactory resolved(Object dependencyNotation)
    UnresolvedCustomPluginResolutionResultFactory unresolved(@Nullable String reason)
}

ResolvedCustomPluginResolutionResultFactory will have a Dependency getDependency().

The reason for all this is that we now have some communicative types, and more options for safely evolving this API if necessary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer having a found/notFound callback instead of a factory plus return type.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just inline the provider method here. I don't think we need two types.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this needs to return a repository. The RepositoryHandler is effectively the container of repositories.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oehme @eljobe it might actually be the case that this is needed because of

- can you please explain why we need to do this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we want to prepend instead of append repositories. The global plugin repositories should have precedence over the ones defined in the buildscript block of a project. It's an unlikely edge case, users will rarely mix the two.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method name is a little long winded. Perhaps just rules would be ok.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm quite confused by this interface. Is it the repository? It seems that it's more like a builder for a repository. What's the usage pattern here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I was thinking a repository is something that provides plugins. I think this kinda follows the PluginPortal way of doing things, maybe it's a Portal instead?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the same pattern like the other plugin repository subtypes. The user configures it and it has an internal method that turns into a plugin resolver.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be Action<? super X>

@ldaley
Copy link
Contributor

ldaley commented Nov 30, 2016

@ethankhall looks like I don't know how to use GitHub code reviews. I added a bunch of comments, but it looks like they weren't saved (or whatever). They should be there now. Some of them no longer hold after the change requests from @oehme.

As for the init script issue, I agree with @oehme.

I'm not quite understanding how the usage patterns of the new API. I think this is indicative of it being a little convoluted.

@ethankhall @oehme @eriwen the quickest way forward here is probably to meet for 30 minutes to discuss synchronously. @eriwen would you mind making this happen?

@ethankhall
Copy link
Contributor Author

@alkemist sounds good! I'm generally avaliable to meet.

@oehme
Copy link
Contributor

oehme commented Nov 30, 2016

@alkemist The user-facing DSL is shown in one of my comments above. Adjusted for the latest changes it looks like this:

pluginRepositories {
  rules {
    description = "The Foobar plugins"
    artifactRepositories {
      maven {
        url = 'foobar'
      }
    }
    pluginResolution {
      if (requestedPlugin.id == "foobar") {
        target.useModule("com.foo:bar:${requestedPlugin.version}")
      }
    }
  }
}

It closely follows the patterns of existing plugin repository types as well as patterns of our dependency resolution API.

I'm up for a short meeting, just let me know when.

Moving PluginId to be a public Interface, and then created an
implementation called DefaultPluginId

Added the first phase of interfaces (inside the class, will move out
later) so that I can start working on the API under the hood.
- Moved PluginRequest to InternalPluginRequest
- Created PluginRequest that InternalPluginRequest extends
- Made the code compile for RuleBasedPluginRepository
Removed PluginId interface and made DefaultPluginId be a class that we
share and part of the public API.
Removing extra classes added by earlier changes:
- Using Actions now
- Using the RepositoryHandler
Also fixing issue Luke pointed out with Action<X> should be
Action<? super X>.
PluginId was pulled into an interface so that we can control the
creation of those instances.
Added notFound(reason) to the API per Stefan's suggestion.
@ethankhall
Copy link
Contributor Author

@eriwen I fixed the merge conflict on this guy.

eriwen added a commit that referenced this pull request Jan 20, 2017
@eriwen
Copy link
Contributor

eriwen commented Jan 21, 2017

This was rebased and merged onto master with tests fixed up by #1226. Closing as delivered.

@eriwen eriwen closed this Jan 21, 2017
eriwen added a commit that referenced this pull request Jan 22, 2017
eriwen pushed a commit that referenced this pull request Jan 22, 2017
1) PluginResolutionServiceResolver was renamed to PluginPortalResolver,
which broke tests that set the url for the portal.
2) We need to make sure to move the buildscript repositories after the
plugin repositories
eriwen added a commit that referenced this pull request Jan 24, 2017
eriwen added a commit that referenced this pull request Jan 24, 2017
@eriwen eriwen reopened this Jan 24, 2017
@oehme
Copy link
Contributor

oehme commented Feb 7, 2017

Closing as superseded by #1343

@oehme oehme closed this Feb 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants