Unzipping artifact created with application plugin

I’ll try to keep it short here. I have a multi-project build where I build one java sub-project with the application plugin and a separate sub-project just with the distribution plugin. The end goal is to have one project which aggregates the artifacts (distZip outputs) from each of these sub-projects and bundles them into a single distribution. Both projects currently build perfectly fine individually and produce an artifact that works, but I want a single zip with the output of both of these projects. My issue comes about when finally trying to combine the two output distributions from these two projects.

I’ve created what I believe is the bare-minimum reproducible version of my project. It contains a root build.gradle (empty), a settings.gradle which includes the two sub-projects (projectA, projectB), and the projects themselves. ProjectB is the java project with the application plugin. ProjectA is the one which tries to extract the distZip output of projectB into a new artifact.


plugins {
    id 'application'

application {
    mainClassName = "com.MainClass"


plugins {
    id 'distribution'

configurations {

dependencies {
    bundleSrc project(path: ':projectA', configuration: 'archives')

task buildBundle(type: Copy){
    from configurations.bundleSrc
        .filter{ println(it.name); it.name.endsWith(".zip")}
        .collect{ zipTree(it) }
    into "$buildDir/bundle"

distributions {
    main {
        contents {
            from buildBundle

Notice how projectA prints the name of each file in bundleSrc. The output when running ./gradlew build is projectB.jar projectB.zip projectB.tar. Gradle knows projectB is outputting those artifacts, but once it tries to unzip the zip, it fails with the error:

Execution failed for task ':projectA:buildBundle'.   
Cannot expand ZIP '<path>\test-project\projectB\build\distributions\projectB.zip' as it does not exist.

Even though projectA depends on projectB, it runs before projectB. If I manually build projectB, and then perform a full build, projectA builds successfully. (as in a ./gradlew :projectB:build then a ./gradlew build builds successfully)

What’s interesting is that if I for example created a projectC which manually used the distribution plugin (as opposed to implicitly with the application plugin) projectA would properly wait for projectC before trying to create the final distribution.

Perhaps there is an easier way to do this. I might be making this more complex than it needs to be. Is there any way I can make it so projectA waits for projectB before trying to build the final distribution? Or is there an easier way to do this in general that I’m just missing?

Here is a fully “working” example: