Gradle list dependency without resolving configuration - gradle

I have a custom task which unpacks all tar/zip dependencies for all configurations.
How do I define an up-to-date check that checks if any of the dependencies have changed, without resolving the configurations.
If I resolve the configuration I can't add dependencies to it later.
Current code:
def dependencyList() {
Set ret = []
configurations.each { conf ->
if (conf.canBeResolved) {
conf.resolvedConfiguration.resolvedArtifacts.each {
if (isArchive(it)) {
ret.add(it.toString())
}
}
}
return ret
}
task extractDeps {
inputs.property 'deps', dependencyList()
....
}
// This block will fail since the compile configuration is already resolved.
dependencies {
compile 'group:name:version#tar'
}

Related

Print sorted list of dependencies for all projects in Gradle build

I want to create a complete list of dependencies for all projects in my Gradle build to track changes over time.
For this purpose, both the list of projects and the list of all dependencies (direct and transitive) must be sorted. Without both, the diff between releases is useless.
My first attempt was
fun listDependencies(project: Project, configName: String) {
val config = project.configurations.findByName(configName) ?: return
println()
println("$configName of module ${project.name}:")
config.allDependencies.map {
" ${it.group}:${it.name}:${it.version}"
}.sorted().forEach {
println(it)
}
}
fun listDependencies(project: Project) {
listDependencies(project, "compileClasspath")
listDependencies(project, "testCompileClasspath")
}
/** Create sorted list of dependencies per module and only for the compileClasspath and testCompileClasspath */
task("listDependencies") {
doLast {
println("Dependency list per project")
allprojects.sortedBy { it.name }
.forEach {
listDependencies(it)
}
}
}
In the output, most versions are null and all transitive dependencies are missing.
I had to force dependency resolution by changing the config.allDependencies above to
config.resolvedConfiguration.resolvedArtifacts.map {
" ${it.moduleVersion}"
}.sorted().forEach {
println(it)
}
This works but gives me a warning that I shouldn't call resolvedConfiguration (Resolving unsafe configuration resolution errors).
What do I have to change to run this task once after the configuration phase only when I ask for it by running Gradle with ./gradlew listDependencies?
We don't need this task in every build.

Using Gradle to build a jar with dependencies with Kotlin-DSL

There is already an answer to the question: how to include all the dependencies in a jar file though it's for Groovy
I'm using gradle with kotlin-dsl and the code is not compatible. I tried to make it work using a few ways including:
tasks.withType<Jar> {
configurations["compileClasspath"].forEach { file: File ->
copy {
from(zipTree(file.absoluteFile))
}
}
}
Though this doesn't work. So how to include the dependencies using kotlin-dsl in gradle?
This will work:
tasks.withType<Jar>() {
configurations["compileClasspath"].forEach { file: File ->
from(zipTree(file.absoluteFile))
}
}
There's no need in copy { ... }, you should call from on the JAR task itself.
Note: Gradle does not allow changing the dependencies after they have been resolved. It means that the block above should be executed only after the dependencies { ... } are configured.
my case
withType<Jar> {
enabled = true
isZip64 = true
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
archiveFileName.set("$project.jar")
from(sourceSets.main.get().output)
dependsOn(configurations.compileClasspath)
from({
configurations.compileClasspath.get().filter {
it.name.endsWith("jar")
}.map { zipTree(it) }
}) {
exclude("META-INF/*.RSA", "META-INF/*.SF", "META-INF/*.DSA")
}
}

Creating a maven wrapper pom.xml from gradle: can't create the <build> element

How do I set the sourceDirectory, testSourceDirectory and build plugins in a pom.xml that I'm creating using the gradle maven-plugin's pom DSL?
When I add build without a Closure to my DSL section, it's ok.. but when I add build { /* anything else, like actual compile plugins */} it gives me this error:
Execution failed for task ':mavenWrapper'.
> No such property: _SCRIPT_CLASS_NAME_ for class: org.apache.maven.model.Model
I'm guessing that gradle is treating build as the task rather than the DSL verb generated by org.sonatype.maven.polyglot.groovy.builder.ModelBuilder.
Is there a way to force build to be treated as part of the DSL? Can it be cast or something?
Right now I'm working around this by using .withXml but it's massively verbose and much less maintainable.
Here's an abbreviated version of what I've got working:
task mavenWrapper {
doLast {
delete 'pom.xml', 'mvnw', 'mvnw.cmd'
pom {
project {
packaging 'pom'
repositories {
repository {
id 'spring-milestones'
name 'Spring Milestones'
url 'https://repo.spring.io/libs-milestone'
snapshots {
enabled 'false'
}
}
}
properties {
'kotlin.compiler.incremental' 'true'
}
/* ******** Problem is here
build {
plugins {
plugin {
// ... etc. etc.
}
}
}
******* */
dependencyManagement {
dependencies {
dependency {
groupId 'org.jetbrains.kotlin'
artifactId 'kotlin-stdlib-jre8'
version "${kotlin_version}"
scope 'compile'
}
}
}
}
}.withXml {
// Workaround for the missing build { ... } section above.
asNode().appendNode('build').appendNode('plugins')
// etc. etc.
}.writeTo("${projectDir}/pom.xml")
exec {
commandLine 'mvn', '-N', 'io.takari:maven:wrapper', '-Dmaven=3.5.0'
}
}
}

How can I invoke Gradle's repository search manually?

As a precondition for building a release version, say acme-widgets-1.0, I would like to search the configured repositories (or a specific repository) to make sure acme-widgets-1.0.jar hasn't already been published. How can I do this with Gradle? Alternatively, is there a way to configure a not-exists dependency for a specific version?
group = 'com.acme'
version = '1.0'
repositories {
jcenter()
}
if (gradle.startParameter.taskNames.contains("release")) {
def taskNames = gradle.startParameter.taskNames
taskNames.add(0, "checkReleaseDoesntExist")
gradle.startParameter.taskNames = taskNames
}
task checkReleaseDoesntExist() {
}
task release() {
println "Building release"
}
checkReleaseDoesntExist.doLast {
println "Checking repositories to make sure release hasn't already been built"
// TODO What do I do here?
}
You could declare a configuration with only the artifacts for which you are trying to see if they are already published.
Upon resolving this configuration, you would have an empty fileset or not.
So something along the lines of:
configurations {
checkRelease { transitive = false }
}
dependency {
checkRelease "$group:$name:$version"
}
task ('checkReleaseDoesntExist') {
doLast {
println "Checking repositories to make sure release hasn't already been built"
try {
if (!configurations.checkRelease.files.isEmpty()) {
// already exists
}
}
catch (ResolveException e) {
// doesn't exist
}
}

Trouble injecting the build block while exporting a Maven pom.xml file from gradle

task writeNewPom {
pom {
project {
/*
build {
plugins {
plugin {
groupId 'GROUP_ID'
artifactId 'maven-ipcentral-plugin'
version '4.7'
executions {}
configuration {
url "http://CENTRAL_REPORTING_SERVER"
logfileprefix "test"
ipcProject = true
businessUnit "FOUR_DIGIT_CODE"
componentEditorsGrouper "ccp-dev"
assetEditorsGrouper "ccp-dev"
username "USERNAME"
}
}
}
}
*/
pluginRepositories {
pluginRepository {
id 'ipcentral-snapshots'
name 'IPCentral Snapshot Repository'
url 'http://PLUGIN_SOURCE/'
snapshots {
enabled = false
}
releases {
enabled = true
}
}
}
profiles {
profile {
id 'inject-cec-credentials'
activation {
activeByDefault = true
}
properties {
username = "USERNAME"
}
}
}
}
}.writeTo("ipcentral/pom.xml")
}
I am attempting to create a pom.xml file using the gradle maven plugin. It must reference a maven plugin designed for central dependency reporting. As it is right now it successfully creates the pom.xml file containing all dependencies, plugin repository info, and profile info. However if the build section is un-commented the I get an error along the lines of:
> No such property: _SCRIPT_CLASS_NAME_ for class: org.apache.maven.model.
If I try something simple like
task writeNewPom {
pom {
project {
build {
}
}
}
}
then I get the same error. It seems that gradle does not recognize build as a valid identifier. I am just hoping for a more elegant solution than manually editing xml through groovy. The only documentation on this that I can find is Gradle docs Chap 53
This is due to the fact that the project {...} closure is delegating to an instance of ModelBuilder which extends Groovy's FactoryBuilderSupport class that already defines a method named build. So instead of configuring the build property of the Maven Model object, the preexisting build method is being called.
To get around this I'd use withXml {...} to configure that portion of your pom.
pom {
project {
// other non-<build> configuration
}
}.withXml {
asNode().appendNode('build').appendNode('plugins').appendNode('plugin').with {
appendNode('groupId', 'GROUP_ID')
}
}.writeTo('pom.xml')
Here is a more detailed example:
.withXml
{
asNode().appendNode('build').appendNode('plugins').with
{
with
{
appendNode('plugin')
.with
{
appendNode('groupId', 'groupId1')
appendNode('artifactId', 'artifactId1')
appendNode('version', 'version1')
}
}
with
{
appendNode('plugin')
.with{
appendNode('groupId', 'groupId2')
appendNode('artifactId', 'artifactId2')
appendNode('version', 'version2')
}
}
}
}
.writeTo("pom.xml")

Resources