Description
Consider the case where your test configuration has commons-lang3, but main does not.
So you think you're adding the signatures only to the test task:
tasks.forbiddenApisTest {
signaturesURLs.add(loadResource("commons-lang3-extra.txt"))
}
But then you get a build failing in forbiddenApisMain
because it can't find commons-lang3's StringUtils
.
This is flaky behaviour, which is why we hadn't noticed it immediately: If forbiddenApisMain
runs first, it will work fine, because the configuration for forbiddenApisTest
hasn't been evaluated yet. But if forbiddenApisTest
runs first, it configures signaturesURLs
, which turns out to be the same collection used by forbiddenApisMain
. Since forbidden APIs depends on the result of compilation, and main always finishes compiling before test, this would only happen in larger projects where there are so many tasks running concurrently that it's possible for the test one to run first.
From quickly reading the code, it would look like each task uses its own collection, but it seems that the convention mapping then stomps all the references with a reference to the collection in the shared extension. So all tasks actually use the same collection object, and thus using +=
/add
isn't actually safe right now.
The workaround is to copy the collection first:
tasks.forbiddenApisTest {
signaturesURLs = signaturesURLs.toMutableSet()
signaturesURLs.add(loadResource("commons-lang3-extra.txt"))
}
Odds are, the same issue exists with all other collections, including bundledSignatures
. But with bundledSignatures
it's less noticeable because you're going to be using the same JDK on main and test.
Ideally, these collections would actually be SetProperty
, with the initial contents of the set coming from the shared extension. But of course, that changes the public API. :(