Hey there, I'm trying to autoactivate the buildsc...
# community-support
b
Hey there, I'm trying to autoactivate the buildscan on several conditions e.g. if in CI or if explicitly required on command line. Handling the CI part is easy but I wasn't able to overcome the
--scan
condition, the following code fails
Copy code
develocity {
    buildScan {
        termsOfUseUrl.set("<https://gradle.com/help/legal-terms-of-use>")
        termsOfUseAgree.set("yes")
        publishing {
            onlyIf {
                (System.getenv("CI") != null) or gradle.startParameter.isBuildScan
            }
        }
    }
}
with a serialization issue
Copy code
1 problem was found storing the configuration cache.
- Gradle runtime: cannot serialize object of type 'org.gradle.initialization.DefaultSettings', a subtype of 'org.gradle.api.initialization.Settings', as these are not supported with the configuration cache.
  See <https://docs.gradle.org/9.0.0/userguide/configuration_cache_requirements.html#config_cache:requirements:disallowed_types>
Maybe you have more ideas on this ?
Actually, it seems my failed attempts always were declaring variables outside the
develocity
block, declaring
startParameter
within
develocity
seem to fix the serialization issue.
p
AFAIK you also don’t need the startParameter
With this code, you can still use
--scan
to upload a BuildScan:
Copy code
val isCI = providers.environmentVariable("CI").isPresent
publishing {
  onlyIf { isCI }
}
But it is basically our code
thank you 1
πŸ‘† 1
b
I have another question, how can we auto activate the build scan, when the project is synced in intellij, in particular with the new develocity intellij plugin?
v
Do you want that the plugin shows helpful information or do you actually want to enable a build scan in addition?
b
For sure I would like the plugin to show helpful information, like configuration performance (e.g. created tasks metrics, etc), but at this point it's only in the build scan. So I would like to have the build scan automatically enabled when run within IJ.
v
That did not really answer my question
Do you want to enable that the plugin shows helpful information, or do you want additionally to the helpful information in the plugin also publish a web-based build scan?
b
Well what I'm trying to say is : both !
Today the plugin doesn't show enough useful (Gradle 9, and develocity ij plugin 1.0.0)
v
Just asking, because you should not need to enable build scans to get information in the plugin, you just have to have new enough develocity plugin applied or injected by the IDE
If you want to enable build scans during IJ sync, you could check for
idea.sync.active
system property in the
onlyIf
But make sure that you do not agree to the ToS of scans.gradle.org for other people. Some FOSS projects tend to use
onlyIf { true }
and also configuring the ToS agreeing in the build script which is a very bad idea. πŸ™‚
b
Excellent thanks. Do mean instead that this line shouldn't be set ?
Copy code
termsOfUseAgree.set("yes")
v
Depends on your context. If this is for a company-internal Develocity server for example, all good most probably. But if this is for example is for a FOSS project you should definitely never set that. Otherwise I clone your project and execute a build, then my personal data was sent do the Gradle server because you agreed to the ToS on my behalf which I did not allow you to. The Develocity docs also warn you to not do that.
Just the same, the
idea.sync.active
should not be checked in the
onlyIf
for a FOSS project. Otherwise I just open your project in my IDE and suddenly my personal data was uploaded to Gradle servers without my consent.
πŸ‘ 1
Without the ToS agreeing it at least is not that bad because I still need to post my consent, but still it would not be too nice to hang the IDE sync waiting for my response the ToS question
b
This warning should definitely be on the termsOfUse setting. I believe folk do that because the question is not remembered I think
v
Well, its in the docs of it. πŸ™‚ If you think it should be somewhere else, tell them. But also just use common sense. I.e. do you really want to and are allowed to agree to the ToU for everyone getting that file? If the answer is similar to "no", "maybe", or "I don't know", then you should not set it. πŸ™‚ Besides that, you can make Gradle remember it by using an init script in your Gradle user home that agrees to the terms of use for all builds you run or to selected ones.
πŸ‘ 1
πŸ‘€ 1
Something similar to this for example to opt-in for all projects that use that ToU URL:
Copy code
import com.gradle.develocity.agent.gradle.DevelocityConfiguration

initscript {
    repositories {
        gradlePluginPortal()
    }
    dependencies {
        classpath("com.gradle.develocity:com.gradle.develocity.gradle.plugin:+")
    }
}

settingsEvaluated {
    pluginManager.withPlugin("com.gradle.develocity") {
        configure<DevelocityConfiguration> {
            buildScan {
                termsOfUseAgree.convention(termsOfUseUrl.map { if (it == "<https://gradle.com/help/legal-terms-of-use>") "yes" else null })
            }
        }
    }
}
thank you 1
p
is the "settingsEvaluated" is closure: ????
v
I don't get your question
p
Got it !!!!
πŸ‘Œ 1
b
Seems like Gradle 9 don't like
Copy code
extensions.configure<com.gradle.develocity.agent.gradle.DevelocityConfiguration>() {}
It outputs the following
Copy code
org.gradle.api.UnknownDomainObjectException: Extension of type 'DevelocityConfiguration' does not exist. Currently registered extension types: [ExtraPropertiesExtension, DevelocityConfiguration]
Tried with
Copy code
extensions.configure<com.gradle.develocity.agent.gradle.DevelocityConfiguration>("develocity") { }
fails with
Copy code
class com.gradle.develocity.agent.gradle.internal.a_Decorated cannot be cast to class com.gradle.develocity.agent.gradle.DevelocityConfiguration (com.gradle.develocity.agent.gradle.internal.a_Decorated is in unnamed module of loader org.gradle.internal.classloader.VisitableURLClassLoader$InstrumentingVisitableURLClassLoader @75a61f4; com.gradle.develocity.agent.gradle.DevelocityConfiguration is in unnamed module of loader org.gradle.internal.classloader.VisitableURLClassLoader$InstrumentingVisitableURLClassLoader @5c22aa46)
And without surprise this return null
Copy code
extensions.findByType<com.gradle.develocity.agent.gradle.DevelocityConfiguration>()?
v
Maybe better use a Groovy DSL init script and leverage is duck-typing
So then just
Copy code
settingsEvaluated {
     pluginManager.withPlugin("com.gradle.develocity") {
         develocity {
             buildScan {
                 termsOfUseAgree.convention(termsOfUseUrl.map { (it == '<https://gradle.com/help/legal-terms-of-use|https://gradle.com/help/legal-terms-of-use>') ? 'yes' : null })
             }
         }
     }
 }
as complete init script
If the used DSL changes, or you also want to support the old enterprise plugin, you need to add accordingly or have some `if`s.
πŸ‘ 1
b
I need to investigate if that's something local, but the lambda in withPlugin is never invoked it seems (both in cli or IJ). Tried on Gradle 8.14.3 / Gradle 9.0.0. In the example above I also tried with
org.gradle.toolchains.foojay-resolver-convention
plugin id, that is appearing in my project's settings.
I forgot that Gradle also has a pluginManager, so one need to scope
pluginManager
to
it
in groovy, otherwise the lookup happens on the Gradle object. Also,
withPlugin
gives an
AppliedPlugin
, so it's necessary to prefix by settings as well.
Copy code
settingsEvaluated { settings->
    logger.lifecycle('settings evaluated')
    settings.pluginManager.withPlugin('com.gradle.develocity') {
        logger.lifecycle('Develocity applied')
        settings.develocity.buildScan {
            logger.lifecycle('auto accepting terms')
            termsOfUseAgree.convention(termsOfUseUrl.map { (it == '<https://gradle.com/help/legal-terms-of-use>') ? 'yes' : null })
        }
    }
}
πŸ‘Œ 1
Actually found a different way to write this in kotlin DSL, using the commodity
withGroovyBuilder
Copy code
initscript {
    repositories {
        gradlePluginPortal()
    }
    dependencies {
        classpath("com.gradle.develocity:com.gradle.develocity.gradle.plugin:+")
    }
}

settingsEvaluated {
    pluginManager.withPlugin("com.gradle.develocity") {
        extensions["develocity"].withGroovyBuilder {
            configureBuildScan(getProperty("buildScan"))
        }
    }
}

fun configureBuildScan(extension: Any) {
    extension.withGroovyBuilder {
        @Suppress("UNCHECKED_CAST")
        (getProperty("termsOfUseAgree") as Property<String>).convention((getProperty("termsOfUseUrl") as Property<String>).map {
            if (it == "<https://gradle.com/help/legal-terms-of-use>") "yes" else ""
        })
    }
}
Out of curiosity should I fill this classloading issue ?
Copy code
class com.gradle.develocity.agent.gradle.internal.a_Decorated cannot be cast to class com.gradle.develocity.agent.gradle.DevelocityConfiguration (com.gradle.develocity.agent.gradle.internal.a_Decorated is in unnamed module of loader org.gradle.internal.classloader.VisitableURLClassLoader$InstrumentingVisitableURLClassLoader @75a61f4; com.gradle.develocity.agent.gradle.DevelocityConfiguration is in unnamed module of loader org.gradle.internal.classloader.VisitableURLClassLoader$InstrumentingVisitableURLClassLoader @5c22aa46)
v
Of course you can also use
withGroovyBuilder
but as most of the script is in Groovy anyway, I'd just use a Groovy init script. πŸ˜„ The
initscript
block you can still leave out, then there is also no potential classloading issue
πŸ‘ 1
thank you 1
The
initscript
you would only need if you need the classes within the script which you no longer use
b
Makes sense !
p
Groovy Builder but most of the script is Groovy so Groovy. !!!!
b
> Groovy Builder but most of the script is Groovy so Groovy. !!!! Nope, it's kotlin dsl
v
What he meant is, you use groovy builder almost everywhere, so there is not really much point in using Kotlin DSL to wrap it, but it would make more sense and would also be nicer if you just used Groovy DSL.
p
ok !!!!!! thats Kotlin dsl (version )