Does the lifecycle of a build differ when called by buildship to import a project?

I have

  • a fresh eclipse installation
  • GRADLE_USER_HOME set as a user env variable (on Windows)
  • $GRADLE_USER_HOME/gradle.properties contains some credentials for authenticating against our local artifactory
  • no additional configuration entered in eclipse/gradle configuration

in this situation, buildship fails to import dependencies (a long list of “could not resolve” errors) whereas running a gradle task from eclipse does work as expected.

Adding debug logging tells me the root cause is of the form

Cause 8: org.gradle.internal.resolve.ModuleVersionNotFoundException: Cannot resolve external dependency org.apache.logging.log4j:log4j-slf4j-impl:2.12.1 because no repositories are defined.
Required by:
    project :xyz

In my case, the relevant repository is added by a plugin in a gradle.projectsEvaluated closure.

The same build loads fine in Intellij.

Is there a difference in the lifecycle of a build when invoked from buildship that would explain this?

Shifting the code in the plugin to project.afterEvaluate allows the build to complete normally so this does suggest there is some difference in how buildship works (vs both vanilla gradle and intellij)

Buildship doesn’t do anything special, it should load the dependencies similarly to IDEA.
Why do you need to use gradle.projectsEvaluated? I think you should declare repositories straight in the plugin application block. Here’s a working example

apply plugin: 'java'
apply plugin: RepoPlugin

dependencies {
    implementation 'com.google.guava:guava:21.0'
}

class RepoPlugin implements Plugin<Project> {
    @Override
    void apply(Project project) {
        def sampleUrl = project.findProperty('sample-repo-url')
        if (sampleUrl) {
            project.repositories.maven {
                url sampleUrl
            }
        }
    }
}

If your plugin happens to be in buildSrc then you can bump into this . I’d suggest to declare the repository URL as a system property in thegradle.properties file.

a plugin is responding to some configuration object exposed to build.gradle and hence has to wait and see what value is supplied by the developer.

I have invariably used gradle.projectsEvaluated for this in the absence of any other way to control when such things fire (this plugin is applying various defaults/conventions so is typically responding to the configuration in total)

I have seen a similar problem in another piece of code, in simplified form I have some code which did

gradle.projectsEvaluated {
    if (project.extensions.myextension.somevalue.get() == 'foo') {
        project.dependencies.add('testImplementation', 'some:dependency:1.2.3')
    }
}

works fine in intellij and gradle, buildship fails with

Cannot change dependencies of configuration ':testImplementation' after it has been included in dependency resolution.

changing my code to fire in project.afterEvaluate is required to make it work.

IMV this is a bug (because buildship is behaving fundamentally differently to gradle itself)