Why does adding archives in a closure behave differently than adding them directly

I have a gradle file that produces a number of jars and I want to add the archives in a loop.

running gradle clean build works fine if I have

signing {
    required { isReleaseVersion }
    sign configurations.archives
}
  artifacts {
    archives puzzleJar
    archives adventureJar
    archives hiqJar
    archives mazeJar
    archives redpuzzleJar
    archives sudokuJar
     archives tantrixJar
    :
}

but if I change the artifacts declaration to

def jarTasks = ["puzzleJar", "adventureJar", "hiqJar", "mazeJar", "redpuzzleJar", "sudokuJar",..., "tantrixJar"]
  artifacts {
    jarTasks.each{ taskName ->
        def artifactName = 'bb4-' + (taskName - 'Jar') + "-$version"
        archives new DefaultPublishArtifact(
                artifactName, "jar", "jar", null, new Date(),
                new File("$buildDir/libs", "${artifactName}.jar"))
    }
 }

then ‘gradle clean build’ gives Execution failed for task ‘:signArchives’. > E:\projects\java_projects\bb4-puzzles\build\libs\bb4-puzzle-1.1.2-SNAPSHOT.jar (The system cannot find the file specified)

gradle build does work if the jar files are already there. It looks like the signing plugin implicitly adds the signArchives task. My hunch is that the closure that adds the archives runs after the signing configuration, but I don’t know why - or how to get it to run first.

My full gradle file is https://raw.github.com/barrybecker4/bb4-puzzles/master/build.gradle note that it imports my common gradle build file https://raw.github.com/barrybecker4/bb4-common/master/bb4.gradle

I am using gradle 1.6.

The difference is not the loop (or timing), but that you are adding a ‘DefaultPublishArtifact’ (which, by the way, is an internal class) instead of an archive task. And since you don’t specify ‘DefaultPublishArtifact.builtBy’, the necessary task dependences cannot be inferred. Replacing the loop body with ‘archives tasks[taskName]’ should solve the problem.

Thank you! That worked wonderfully and is much simpler that what I was trying to do. Instead of using the names of the jar tasks, I can use the instances directly and it becomes a one liner. The mavenDeployer can use a similar loop. Here is the now working code

def jarTasks = [puzzleJar, adventureJar, hiqJar, mazeJar, redpuzzleJar, sudokuJar, tantrixJar]
  artifacts {
    jarTasks.each{ jarTask -> archives jarTask }
}
  uploadArchives {
    repositories {
        mavenDeployer {
            // Maven does not allow more than one jar per pom file. Filter is used to make many artifacts.
            jarTasks.each{ jarTask ->
                def jarName = 'bb4-' + jarTask.name - 'Jar'
                addFilter(jarTask.name) {artifact, file ->
                    artifact.name == jarName
                }
            }
        }
    }
}