Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dependencies should be pulled during gradle execution time #123

Closed
nathanabercrombie opened this issue Aug 7, 2016 · 20 comments
Closed
Assignees
Milestone

Comments

@nathanabercrombie
Copy link

As a best practice, dependencies should be pulled during gradle execution time. This means that this plugin should not download the huge dependency files during configuration.

Downloading at configuration time is bad practice because when a large project configures, it configures every module, regardless of what it is going to run. So if I have a large gradle project, and one of the modules has this plugin applied, but I am building a different module, it will still pull the dependency. This does not scale well at all for large projects.

@zolotov
Copy link
Member

zolotov commented Aug 7, 2016

As far as I understand in this case none of the tools (IDEs, Review Tools) which relies on gradle project model will be able to properly handle such dependencies. This is unacceptable for this plugin. If you aware of how to deal with it – contributions are welcome.

@nathanabercrombie
Copy link
Author

I have not read through the implementation for this project, but the way that plugins should handle injecting dependencies is by:

  1. Adding the repository for the dependencies during configuration (plugin.apply)
    project.repositories.maven { url YOURURL }
  2. After determining which dependencies, adding them during configuration
    project.dependencies { compile "com.intellij.org:blah:blah" }

Then, if this project needs to be compiled (based on the task given to gradle), only then will the dependencies get pulled. All tools that are based on gradle will work fine. I have built a plugin this way, and it is the recommended way (unfortunately it is closed source, so I cannot show you it).

I'll take a look at this plugin's source when I get the chance.

@zolotov
Copy link
Member

zolotov commented Aug 8, 2016

@nathanabercrombie thanks for the answer. IntelliJ dependencies are not the maven dependency

What the plugin does during the configuration:

  1. it downloads idea.zip, which is the build of particular IDEA version
  2. it extracts zip, create local ivy repo with the list of jar (from idea.zip) which should be used as dependencies
  3. attaches ivy dependecy via project.dependencies { compile "com.intellij.org:blah:blah" }

So it cannot attach dependencies with project.dependencies { compile "com.intellij.org:blah:blah" } until it downloads idea.zip

@nathanabercrombie
Copy link
Author

I suspected that was what was happening. The only solution to this is if you host the ivy repo remotely. I am not sure what Idea's policies are on uploading those jars to something like maven central, but it wouldn't be hard to script it.

This is a deal breaker for my project. I have a work around though: my company provides an internal repository host, so I may just upload the required jars there. There are other really cool features of this plugin, so I was hoping to use it.

@zolotov
Copy link
Member

zolotov commented Aug 9, 2016

I have a work around though: my company provides an internal repository host, so I may just upload the required jars there

If this a solution for you then you can upload IDEA zips to your internal maven repository. You can use distributions and pom-files from https://www.jetbrains.com/intellij-repository/releases or https://www.jetbrains.com/intellij-repository/snapshots. Then substitute repo host url via intellij.intellijRepo extension property. By default it is https://www.jetbrains.com/intellij-repository.

There are other really cool features of this plugin, so I was hoping to use it.

What kind of features do you mean? I think I can extract them so you'll be able to use them without downloading IDEA distribution.

@nathanabercrombie
Copy link
Author

Hey, I figured out a pretty elegant solution. This passes my test of:

  • gradle tasks should not download any compile time dependencies
  • gradle assemble should compile with no issues

I did this experiment with the java plugin, but I am sure it can be adapted to your plugin

repositories {
    // We pull from the same repository as before
    maven { url "https://www.jetbrains.com/intellij-repository/releases" }
}

configurations {
    // We add a new "configuration" which lets us do some crazy magic
    ideaPluginPrep
}

// Of course, get ideaVersion however you want
ext.ideaVersion = "145.2070.6"

dependencies {
    // Our new configuration is dependent on the specified idea version
    ideaPluginPrep "com.jetbrains.intellij.idea:ideaIC:$ideaVersion"

    // And here is the magic.  The compile dependency depends on all jars found in 'lib' directory
    compile fileTree("$buildDir/ideaLib/$ideaVersion/lib") {
        // and that lib directory is created by this other task
        builtBy 'prepareIntellijLibraryDirectory'
    }
}

// This task unzips the zip downloaded into the build/ideaLib/$version directory
task prepareIntellijLibraryDirectory {
    doLast {
        // the dereference of configuration.ideaPluginPrep must be done in an action, not in the configuration
        // So we put all this in the doLast block
        copy {
            // configurations.ideaPluginPrep.asPath will include all the dependencies defined above, so this
            // may not work if you include multiple dependencies in ideaPluginPrep above.
            from file(configurations.ideaPluginPrep.asPath)
            outputDir = file("${buildDir}/ideaLib/$ideaVersion")
        }
    }
}

@nathanabercrombie
Copy link
Author

What kind of features do you mean?

Hopefully you can integrate the above solution, but, the features I was referring to are:

  • Automatic modification / packing of plugin.xml
  • Publishing to idea repo
  • runIdea task and all that good stuff
  • any new features you add in the future

@zolotov
Copy link
Member

zolotov commented Aug 11, 2016

compile.builtBy dependency looks promising, thank you! I'll try to implement something similar.

Hopefully you can integrate the above solution, but, the features I was referring to are:

I'm going to reimplement all tasks one by one as part of #110 issue. So they will be available without IDEA dependency, the will have cleaner configurations (via task extension, not via intellij extension). In the 2.0-SNAPSHOT I reimplemented PublishTask. Building, packing plugin, running IDEA and modification plugin.xml tasks are on the plan.

@zolotov
Copy link
Member

zolotov commented Jan 5, 2017

I failed to implement it so far. A suggested solution with a fileTree dependency won't allow to attach sources.
Another approach with resolving ivy-dependency on config.resolutionStrategy.eachDependency still leads to downloading idea during gradle tasks task.
I postpone the issue for a while

@zolotov zolotov modified the milestones: 0.3.0, 0.2.0 Jan 5, 2017
@raniejade
Copy link
Contributor

Any ETA on this?

@zolotov
Copy link
Member

zolotov commented Aug 8, 2017

@raniejade no, contributions are welcome

@raniejade
Copy link
Contributor

I don't think this will be solved without adding a new feature into gradle, is there any particular reason we cant publish to a maven repo the jars in idea.zip?

@zolotov
Copy link
Member

zolotov commented Jan 10, 2018

@raniejade Alexey well described the situation in the related issue at Gradle issue tracker

@oehme
Copy link

oehme commented Mar 12, 2018

I thought about this a bit more and there is a new hook that seems like it could give you what you need: Configuration.withDependencies allows you to lazily create dependencies only when that Configuration is actually needed. So you could create your custom repository in such a withDependencies hook. This exists since Gradle 4.6 I think.

@zolotov
Copy link
Member

zolotov commented Mar 12, 2018

@oehme sounds promising! I'll try it and will tell about the results.

@DreierF
Copy link
Contributor

DreierF commented Sep 30, 2019

Has there been any progress on this?

@zolotov
Copy link
Member

zolotov commented Sep 30, 2019

@DreierF there is zolotov/delay_dependency_resolving branch, you're very welcome to help with it

@raniejade
Copy link
Contributor

@zolotov does this mean that this is fixed? 🤞

@zolotov
Copy link
Member

zolotov commented May 6, 2020

@raniejade yes, should be available in 0.5-SNAPSHOT. In order to see the stacktrace of dependency resolution, run it with --debug

@raniejade
Copy link
Contributor

So good, thanks @zolotov!

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

No branches or pull requests

5 participants