Is there a way to selectively remove certain artifacts from the Gradle cache?

It’s dead-simple in Maven to get rid of certain artifacts in its repository cache.

For example, if I’d like to just remove every artifact with a groupId of ‘de.huxhorn.*’ I’d simply execute ‘rm -rf ~/.m2/repository/de/huxhorn’.

The Gradle cache at ‘~/.gradle/caches’ is a bit more complex than that so I wouldn’t dare to manually interfere with it.

  • modules-2

  • files-2.1

  • metadata-2.12

  • metadata-2.6

Is there a simple way to achieve a similar result? One that would still work with future Gradle versions, ideally a task that would just tell Gradle itself to get rid of the unwanted artifacts?

The rationale for this is that I’d like to cache ~/.gradle in a Travis build, but without risking a polluted cache. Therefore I’d like to make sure that previously produced artifacts are removed from the cache while keeping artifacts that are simply downloaded.

At the moment there is no API for that. The gradle cache layout is using an “internal” format that changes over time depending on the features we’re working on.

I don’t understand your usecase with travis. “produced artifacts” during a build usually don’t end up in the gradle cache at all. maybe just running gradle clean build is the way to go?

The Travis build is executing two Gradle builds A and B where project B depends on artifacts built in project A. So the artifacts of A are considered external artifacts by B and would end up in the Gradle cache.

Less abstract: https://github.com/huxi/sulky/blob/master/.travis.yml and https://github.com/huxi/lilith/blob/master/.travis.yml

I couldn’t find a better way to ensure that project B (lilith) will still build after a change to project A (sulky).

If I’d remove an artifact from A that is actually used by B then it would appear like B would still build (using the a previously built artifact) while it would actually fail in case of a clean build since the missing artifact couldn’t be resolved anymore.

We have a similar issue in our closed-source in-house project and circumvent this by removing ~/.m2/repository/[group-directory] and the whole ~/.gradle/caches before executing a Jenkins build. But this isn’t ideal since it involves removal of all cached artifacts, therefore wasting quite some time.

So there is no issue in case of a single Gradle build but there are issues in case of a Gradle build depending upon some other build, either Maven or Gradle.

Ideally, some public hook into the internal Gradle cache would be able to selectively get rid of some parts of it, e.g. “if the groupId starts with ‘foo’ then flush its cache entry”.

Not sure what you are trying to accomplish here, but I don’t think that removing artifacts from the cache is going to be the right solution. Contrary to Maven Local, the Gradle cache is a cache in the true sense of the word. Its only purpose is to improve performance. It should never affect the behavior of a build.

Hm. It seems that SNAPSHOT dependencies aren’t put into ‘~/.gradle/caches//modules-2’ so it’s possible that this really isn’t an issue at all.

I simply want to ensure that there are no traces of any previously built SNAPSHOT dependencies in the build server while preventing a redownload of all the other (release) dependencies since that would be pretty wasteful.

Project B depends on artifacts of Project A. I want to make sure that those artifacts are really created by the latest build of Project A (that is also performed in the same CI server job) and not be some older build.

Snapshots are cached like static versions but expire after some time (24 hours by default). To make sure you always get the latest snapshots, use:

configurations.all {
    resolutionStrategy.cacheDynamicVersionsFor 0, "seconds"
}

Note that dependencies accessed via the file system (e.g. Maven repos with a ‘file:///’ URL) aren’t currently cached.

Ah, ok. That’s the reason. My snapshots are indeed in a ‘file://’ repository.