Support configuration cache
Newest version of axion-release-plugin doesn't support configuration cache. Here you can see why it fails:
./gradlew currentVersion --configuration-cache
2 problems were found storing the configuration cache, 1 of which seems unique.
- Task `:currentVersion` of type `pl.allegro.tech.build.axion.release.OutputCurrentVersionTask`: invocation of 'Task.project' at execution time is unsupported.
See https://docs.gradle.org/6.8.3/userguide/configuration_cache.html#config_cache:requirements:use_project_during_execution
Both problems are related with using Project during task execution:

Here you can see how to resolve typical problems with using Project inside a task: https://docs.gradle.org/6.8.3/userguide/configuration_cache.html#config_cache:requirements:use_project_during_execution
It's also related to that issue: https://github.com/gradle/gradle/issues/13490
@wyhasany thx for pointing it out, I'll fix this
It will take a while, almost every tasks uses project to reconfigure some properties at runtime ;(
did older version work ok?
To be honest I don't know. I've tested it only with newest version. However I don't think so :)
I think so too. Please be assured that from now on we'll refactor each task to support configuration cache during regular development!
...as of 1.13.6 the following tasks fail when doing 'release':
- Task `:release` of type `pl.allegro.tech.build.axion.release.ReleaseTask`: invocation of 'Task.project' at execution time is unsupported.
See https://docs.gradle.org/7.4.2/userguide/configuration_cache.html#config_cache:requirements:use_project_during_execution
- Task `:verifyRelease` of type `pl.allegro.tech.build.axion.release.VerifyReleaseTask`: invocation of 'Task.project' at execution time is unsupported.
See https://docs.gradle.org/7.4.2/userguide/configuration_cache.html#config_cache:requirements:use_project_during_execution
@bgalek starting to look through this one. Worked through a simple slice below to illustrate the nature of required changes. Biggest challenge is maintaining VersionConfig compatibility with existing users while migrating to managed properties. Will see what options (if any) exist to accomplish that.
Primary activity to make tasks configuration-cache compatible is to remove use of 'project'.
One slice for LocalOnlyResolverFactory (nested in GradleAwareContext):
// existing code: pl.allegro.tech.build.axion.release.infrastructure.config.LocalOnlyResolverFactory
static LocalOnlyResolver create(Project project, VersionConfig config) {
boolean baseValue = project.hasProperty(LOCAL_ONLY) || config.localOnly
return new LocalOnlyResolver(baseValue)
}
// changes to remove project dependency (using managed properties)
// in plugin, maintain reference to versionConfigExtension
def versionConfigExtension = project.extensions.create(VERSION_EXTENSION, VersionConfig, project)
// where localOnly is Property<Boolean>; convention sets its default (plugin consumers can optionally set a value, if not set the convention will be used)
versionConfigExtension.localOnly.convention(project.hasProperty(LOCAL_ONLY) )
// in VersionConfig
// BREAKING CHANGE if done this way, changes type of variable;
// consumers would need to do localOnly.set(true) vs localOnly = true
// need to investigate compatibility options to not break existing users of these properties, while migrating to managed properties
@Input
def Property<Boolean> localOnly;
// in tasks (code is partway there already)
@Nested
def VersionConfig versionConfig;
// in task execution method; note that property is only resolved via get() when required
def localOnlyResolver = new LocalOnlyResolver(versionConfig.localOnly.get())
// ... use localOnlyResolver
... in the end, the same result is achieved: create a LocalOnlyResolver based on the resolved configuration at execution time.
Looks like this will be clean for Groovy consumers, but not for Kotlin consumers of the plugin:
Note that Gradle Groovy DSL generates setter methods for each Property-typed property in a task implementation. These setter methods allow you to configure the property using the assignment (=) operator as a convenience.
In Kotlin DSL, the set() method on the property needs to be used instead of =.
(from: https://docs.gradle.org/current/userguide/lazy_configuration.html#lazy_configuration)
Thoughts on best release target to tackle this partially-breaking change?
@cloudshiftchris I'm ok with 1.14.0 release with realse notes explaining what people need to change
Excellent. Into this now, it will take a bit to wade through it all.
Seeing this issue is still opened, I'll share that I started observing the plugin throwing an error when running with Gradle 8.1 (which has the Configuration Cache feature stabilized)
I apply plugin within my own convention plugin:
class VersioningPlugin : Plugin<Project> {
override fun apply(target: Project): Unit = with(target) {
if (this != rootProject) throw GradleException("Versioning plugin can be applied to the root project only")
pluginManager.apply(ReleasePlugin::class.java)
val scmConfig = extensions.getByType<VersionConfig>()
allprojects { project ->
project.version = scmConfig.version
}
}
which should somewhat transform into what Basic Usage section presents.
The error is
FAILURE: Build failed with an exception.
* What went wrong:
Configuration cache problems found in this build.
2 problems were found storing the configuration cache.
- Plugin 'com.starter.versioning': external process started '/usr/local/bin/git --version'
See https://docs.gradle.org/8.1/userguide/configuration_cache.html#config_cache:requirements:external_processes
- Plugin 'com.starter.versioning': external process started '/usr/local/bin/git config --system --show-origin --list -z'
See https://docs.gradle.org/8.1/userguide/configuration_cache.html#config_cache:requirements:external_processes
See the complete report at file://{project_path}/build/reports/configuration-cache/bw6o1r9owtj2rruhd9167sy1u/663y7tyiq194f3u0xfz72ugjn/configuration-cache-report.html
> Starting an external process '/usr/local/bin/git --version' during configuration time is unsupported.
> Starting an external process '/usr/local/bin/git config --system --show-origin --list -z' during configuration time is unsupported.
+
one of stacktraces from `configuration-cache-report.html`
org.gradle.api.InvalidUserCodeException: Starting an external process '/usr/local/bin/git --version' during configuration time is unsupported.
at org.gradle.configurationcache.initialization.DefaultConfigurationCacheProblemsListener.onExternalProcessStarted(ConfigurationCacheProblemsListener.kt:87)
at org.gradle.configurationcache.InstrumentedInputAccessListener.externalProcessStarted(InstrumentedInputAccessListener.kt:110)
at org.gradle.internal.classpath.Instrumented.externalProcessStarted(Instrumented.java:501)
at org.gradle.internal.classpath.Instrumented.externalProcessStarted(Instrumented.java:509)
at org.gradle.internal.classpath.Instrumented.start(Instrumented.java:363)
at org.eclipse.jgit.util.FS.readPipe(FS.java:1379)
at org.eclipse.jgit.util.FS.readPipe(FS.java:1341)
at org.eclipse.jgit.util.FS.discoverGitSystemConfig(FS.java:1530)
at org.eclipse.jgit.util.FS.getGitSystemConfig(FS.java:1627)
at org.eclipse.jgit.util.SystemReader$Default.openSystemConfig(SystemReader.java:86)
at org.eclipse.jgit.util.SystemReader.getSystemConfig(SystemReader.java:363)
at org.eclipse.jgit.util.SystemReader.getUserConfig(SystemReader.java:311)
at org.eclipse.jgit.internal.storage.file.FileRepository.<init>(FileRepository.java:161)
at org.eclipse.jgit.lib.BaseRepositoryBuilder.build(BaseRepositoryBuilder.java:625)
at org.eclipse.jgit.api.Git.open(Git.java:93)
at org.eclipse.jgit.api.Git.open(Git.java:73)
at pl.allegro.tech.build.axion.release.infrastructure.git.GitRepository.<init>(GitRepository.java:70)
at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:67)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:484)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:72)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:59)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:263)
at org.gradle.internal.classpath.intercept.CallInterceptorsSet$DecoratingCallSite.access$401(CallInterceptorsSet.java:128)
at org.gradle.internal.classpath.intercept.CallInterceptorsSet$DecoratingCallSite$4.callOriginal(CallInterceptorsSet.java:180)
at org.gradle.internal.classpath.intercept.CallInterceptorsSet$1.doIntercept(CallInterceptorsSet.java:54)
at org.gradle.internal.classpath.intercept.CallInterceptorsSet$DecoratingCallSite.callConstructor(CallInterceptorsSet.java:177)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:277)
at pl.allegro.tech.build.axion.release.infrastructure.di.ScmRepositoryFactory.create(ScmRepositoryFactory.groovy:23)
at pl.allegro.tech.build.axion.release.infrastructure.di.ScmRepositoryFactory$create.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139)
at pl.allegro.tech.build.axion.release.infrastructure.di.VersionResolutionContext.create(VersionResolutionContext.groovy:43)
at pl.allegro.tech.build.axion.release.infrastructure.di.VersionResolutionContext$create.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:148)
at pl.allegro.tech.build.axion.release.infrastructure.di.VersionSupplier.resolve(VersionSupplier.groovy:10)
at pl.allegro.tech.build.axion.release.infrastructure.di.VersionSupplier$resolve.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:148)
at pl.allegro.tech.build.axion.release.infrastructure.di.MemoizedVersionSupplier.resolve(VersionSupplier.groovy:25)
at pl.allegro.tech.build.axion.release.infrastructure.di.MemoizedVersionSupplier$resolve.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:148)
at pl.allegro.tech.build.axion.release.domain.VersionConfig$_versionProvider_closure4.doCall(VersionConfig.groovy:221)
at pl.allegro.tech.build.axion.release.domain.VersionConfig$_versionProvider_closure4.doCall(VersionConfig.groovy)
The stacktrace points at pl.allegro.tech.build.axion.release.infrastructure.git.GitRepository.<init>(GitRepository.java:70) as the offender.
Related gradle docs: https://docs.gradle.org/8.1/userguide/configuration_cache.html#config_cache:requirements:external_processes
The interesting part is I don't observe the error at every run, it pops up at occasionally (a guess: when gradle tries to create new configuration cache entry?)
Any update on this? axion-release-plugin is currently blocking us from enabling configuration cache.
I'm able to consistently reproduce the configuration cache problem by stopping the gradle daemon beforehand:
./gradlew --stop && ./gradlew currentVersion
The issue appears to stem from JGit attempting to load the system config. You can disable this feature in JGit using the GIT_CONFIG_NOSYSTEM environment variable. Using the reproducer above this now successfully supports the configuration cache:
./gradlew --stop && GIT_CONFIG_NOSYSTEM=true ./gradlew currentVersion
I have not yet found any time to do this fix, I'll appreciate a PR :)
Hope to release with a fix soon
@bgalek @SmialyKot are you sure this is fixed? I got this on 1.7.0
Calculating task graph as configuration cache cannot be reused because file '.git/config' has changed.
having only axion in place, if I remove it - I don't have this issue anymore