How do I create a dependency between a custom (non-Java) task and a MavenPublication?

I have a custom (exec) task that produces two tarballs (FWIW, they have two different artifactIds). I’m able to publish those two tarballs to a local maven repo, using code that looks essentially like this:

group "org.myorg"
version '1.2.3'
task myCustomTask(type: Exec) {
    outputs.files("$buildDir/path/to")
    commandLine("something that creates first.tar.gz and second.tar.gz")
}
  publishing {
  publications {
    x(MavenPublications) {
      artifactId 'foo'
      classifier 'bin'
      extension 'tar.gz'
      from "$buildDir/path/to/first.tar.gz"
    }
    y(MavenPublications) {
      artifactId 'bar'
      classifier 'bin'
      extension 'tar.gz'
      from "$buildDir/path/to/second.tar.gz"
    }
  }
}

If I build the “gradle myCustomTask” target, I see the tarballs show up in my build directory, and then the “publishToMavenLocal” target publishes those files locally to “~/.m2/repository/org/myorg/foo/foo-1.2.3-bin.tar.gz” and “~/.m2/repository/org/myorg/bar/bar-1.2.3-bin.tar.gz”. However, there’s no dependency graph between the two, so if I try to publish on a clean repo, nothing gets built.

What’s the right way to tell Gradle that those publications have a dependency on “myCustomTask”?

Here’s a partial solution I’ve found, but it doesn’t seem quite right:

task myCustomTask(type: Exec) {
   outputs.files("$buildDir/path/to")
   commandLine("something that creates first.tar.gz and second.tar.gz")
}
task myFooArtifact(type: Tar, dependsOn: myCustomTask) {
  from tarTree("$buildDir/path/to/first.tar.gz")
}
task myBarArtifact(type: Tar, dependsOn: myCustomTask) {
  from tarTree("$buildDir/path/to/second.tar.gz")
}
publishing {
  publications {
    x(MavenPublication) {
      artifact myFooArtifact {
        artifactId 'foo'
        classifier 'bin'
        extension 'tar.gz'
      }
    }
    y(MavenPublication) {
      artifact myBarArtifact {
        artifactId 'bar'
        classifier 'bin'
        extension 'tar.gz'
      }
    }
  }
}

Yes, I can publishToMavenLocal from a clean build and get both artifacts, but if I look in my build directory, I see that the myFooArtifact and myBarArtifact tasks have un-tarred and re-tarred the file (which I don’t want to happen, as this changes the MD5 hash of the artifact, and myCustomTask also produces a list of expected MD5 hashes which no longer match).

I think that the key part is something vaguely like this:

def myFooArtifact = file("$buildDir/path/to/first.tar.gz", buildBy: myCustomTask)

but I don’t seem to be able to find the right syntax. Can anyone help me find the syntax to say “file X is an artifact, and it’s produced by task Y?”

Try this:

apply plugin: 'maven-publish'
  group "org.myorg"
version '1.2.3'
  task myCustomTask(type: Exec) {
    ext.firstTar = file("$buildDir/path/to/first.tar.gz")
    ext.secondTar = file("$buildDir/path/to/first.tar.gz")
    outputs.files(firstTar, secondTar)
    commandLine("something that creates first.tar.gz and second.tar.gz")
}
  publishing {
    publications {
        x(MavenPublication) {
            artifactId 'foo'
            artifact(myCustomTask.firstTar) {
                builtBy myCustomTask
                classifier = 'bin'
                extension = 'tar.gz'
            }
        }
        y(MavenPublication) {
            artifactId 'bar'
            artifact(myCustomTask.secondTar) {
                builtBy myCustomTask
                classifier = 'bin'
                extension = 'tar.gz'
            }
        }
    }
}

Moving the path to the tarballs to the task isn’t necessary.

Key classes: Main configuration closure is backed by MavenPublication which has an artifact method.

From there you can find the MavenArtifact, which has a builtBy method.

Thanks, Sterling…that got me unstuck!

I had tried something very close to what you suggested, namely:

artifact myCustomTask.firstTar { ... }

but gradle complained “Could not find method firstTar()”

I hadn’t appreciated that it parses differently than:

artifact(myCustomTask.firstTar) { ... }

Thanks again for setting me straight!

Yep, it has to do with how we translate the into method calls. It’s ambiguous without the parentheses.