This message was deleted.
# community-support
s
This message was deleted.
c
is it perhaps this:
Copy code
The consumer was configured to find a runtime of a library compatible with Java 11
combined with the Java 8 toolchain?
e
I don't understand what you are saying
c
access-ai
is looking for libraries from those projects compatible with Java 11. You’ve stated those projects use Java 8.
e
Are you saying that Java 11 is not backwards compatible with Java 8?
access-ai
uses
Copy code
java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(11)
    }
}
c
The project it’s consuming don’t appear to be providing metadata on their Java compatibility:
Copy code
None of the consumable configurations have attributes.
…not sure what causes that. May be worth reviewing how those ones are built, is everyone using the same Gradle version, etc.
e
…not sure what causes that.
Thank you for being honest
is everyone using the same Gradle version?
😆 😅 🤣 😂 I think our project has more different versions of Gradle wrapper than there are stars in the universe...
c
understood. that could contribute to the issue as newer Gradle version produce/expect metadata that may not be generated with older versions. Would need to dig to understand how to configure this.
e
Yes, in my experience, the various outdated versions of the Gradle wrapper are a plague on our project... I have been down this road before, and was ultimately defeated in trying to resolve it... the gradle wrapper update mechanism is effectively broken in terms of developer experience... it is very hostile to use.
This is perhaps why we have so many version of Gradle wrapper, because no-one likes the barrier to keeping things up-to-date
c
./gradlew wrapper
(twice) will do the upgrade.
e
I don't believe you, but I will try it... 🤨 Do you really mean
./gradlew wrapper
? Usually, I use
gradle wrapper
which is always the latest version of Gradle...
c
Docs. At the root of a project you can do
./gradlew wrapper --gradle-version 7.5.1
.
e
Copy code
eric.kolotyluk@Y2RCV7009N access-ai % ./gradlew wrapper
fails twice
c
error?
e
Copy code
eric.kolotyluk@Y2RCV7009N access-ai % ./gradlew wrapper --gradle-version 7.5.1

FAILURE: Build failed with an exception.

* Where:
Build file '/Users/eric.kolotyluk/git/autonomous-iam/access/access-ai/build.gradle' line: 266

* What went wrong:
A problem occurred evaluating root project 'access-ai'.
> Could not resolve all files for configuration ':runtimeClasspath'.
   > Could not resolve project :observability:bundle.
     Required by:
         project :
         project : > project :common-utils
      > No matching configuration of project :observability:bundle was found. The consumer was configured to find a runtime of a library compatible with Java 11, packaged as a jar, and its dependencies declared externally but:
          - None of the consumable configurations have attributes.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at <https://help.gradle.org>

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See <https://docs.gradle.org/6.8.3/userguide/command_line_interface.html#sec:command_line_warnings>

BUILD FAILED in 502ms
This is precisely why Gradle wrapper is such a disaster... It sanity checks the gradle files, and refuses the upgrade until it is happy
c
ah. it isn’t sanity checking them, it’s loading the configuration model. Gradle work (lifecycle) is separated into configuration-time and execution-time - you have some janky code that is doing expensive actions at configuration-time.
that would be an error regardless of running the wrapper (or any Gradle task).
one workaround for that code is to move the setting of attributes into a
doFirst
block.
Copy code
jar {
    archiveFileName = "${project.name}.jar"
    doFirst {
        manifest {
            attributes('Main-Class': 'com.forgerock.access.access.Main',
                    'Class-Path': configurations.runtimeClasspath.files.collect { "libs/$it.name" }.join(' ') // line 266
            )
        }
    }
}
e
I agree we probably have "some janky code" -- we probably have lots of "some janky code"
Copy code
jar {
    archiveFileName = "${project.name}.jar"
    doFirst {
        manifest {
            attributes('Main-Class': 'com.forgerock.access.access.Main',
                       'Class-Path': configurations.runtimeClasspath.files.collect { "libs/$it.name" }.join(' ')
            )
        }
    }
}
Same error
c
that should now allow you to run the wrapper. It still still fail when executing the
jar
task, as all we did is move the problem from configuration time to execution time.
e
Copy code
eric.kolotyluk@Y2RCV7009N access-ai % ./gradlew --version

------------------------------------------------------------
Gradle 7.5.1
------------------------------------------------------------
🥳
After cleaning up the
build.gradle
errors because of version 7.5.1, I am left with
Copy code
eric.kolotyluk@Y2RCV7009N access-ai % ./gradlew clean build

FAILURE: Build failed with an exception.

* What went wrong:
Could not determine the dependencies of task ':copyLibs'.
> Could not resolve all task dependencies for configuration ':runtimeClasspath'.
   > Could not resolve project :observability:bundle.
     Required by:
         project :
         project : > project :common-utils
      > No matching configuration of project :observability:bundle was found. The consumer was configured to find a runtime of a library compatible with Java 11, packaged as a jar, preferably optimized for standard JVMs, and its dependencies declared externally but:
          - None of the consumable configurations have attributes.

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at <https://help.gradle.org>

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See <https://docs.gradle.org/7.5.1/userguide/command_line_interface.html#sec:command_line_warnings>
c
how is the dependency on
common-utils
defined in build.gradle?
e
Copy code
//JAS libraries
    implementation project(":service-commons")
    implementation project(":service-config")
    implementation project(":modules-api")
    implementation project(":common-utils")
    implementation project(":encrypt-utils")
    implementation project(":gcp-utils")
    implementation project(":jas-rest-client-java")
    implementation project(":event-lib")
Copy code
include ':observability:bundle'
project(':observability').projectDir = file('../observability')
project(':observability:bundle').projectDir = file('../observability/bundle')

include ':service-commons'
project(":service-commons").projectDir = file("../../autonomous-commons/service-commons")

include ':service-config'
project(":service-config").projectDir = file("../../autonomous-commons/service-config")

include ':modules-api'
project(":modules-api").projectDir = file("../../modules/api")

include 'common-utils'
project(":common-utils").projectDir = file("../../utils")

include 'gcp-utils'
project(":gcp-utils").projectDir = file("../../autonomous-commons/gcp-utils")

include 'encrypt-utils'
project(":encrypt-utils").projectDir = file("../../jas/common-utils")

include ':jas-rest-client-java'
project(":jas-rest-client-java").projectDir = file("../../autonomous-commons/jas-rest-client-java")

include 'event-lib'
project(":event-lib").projectDir = file("../../autonomous-commons/event-lib")
c
thx. that include the sub-projects - in the main build.gradle is it doing something like
implementation(project(":observability:bundle"))?
e
Yes,
implementation project(':observability:bundle')
Copy code
include ':observability:bundle'
project(':observability').projectDir = file('../observability')
project(':observability:bundle').projectDir = file('../observability/bundle')
c
and is
:observability:bundle
creating a jar library?
e
Is it a naming problem with the jar file?
c
don’t think so, that’s all handled internally.
does this work:
./gradlew :observability:bundle:clean :observability:bundle:jar
e
Copy code
eric.kolotyluk@Y2RCV7009N access-ai % ./gradlew :observability:bundle:clean :observability:bundle:jar

FAILURE: Build failed with an exception.

* What went wrong:
Task 'clean' not found in project ':observability:bundle'.

* Try:
> Run gradlew tasks to get a list of available tasks.
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at <https://help.gradle.org>

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See <https://docs.gradle.org/7.5.1/userguide/command_line_interface.html#sec:command_line_warnings>

BUILD FAILED in 423ms
c
thats odd. Typically for a jar-producing project it would have the standard lifecycle tasks (
clean
etc). what plugins does that project apply?
e
I removed the version declarations, so now I get
c
suspect that the bundle project is missing configuration to expose its artifacts for consumption.
e
I seem to recall the snapshot version caused some problems in the past, but it did not help this time...
c
that project should have the below specified to create a JAR that other projects can consume:
Copy code
plugins {
    id 'java-library'
}
is that for
:observability:bundle
? Suspect it’s not as the
clean
task was missing there.
1
As indicated above, this plugin adds basic building blocks for working with JVM projects. Its feature set has been superseded by other plugins, offering more features based on your project type. Instead of applying it directly to your project, you should look into the
java-library
or
application
plugins or one of the supported alternative JVM language.
^^^ for the
java
plugin. Should be using
java-library
to create a JAR.
better (
java
is redundant).
e
Copy code
eric.kolotyluk@Y2RCV7009N access-ai % ./gradlew clean build                                          

FAILURE: Build failed with an exception.

* What went wrong:
Could not determine the dependencies of task ':copyLibs'.
> Could not resolve all task dependencies for configuration ':runtimeClasspath'.
   > Could not resolve project :observability:bundle.
     Required by:
         project :
         project : > project :common-utils
      > No matching configuration of project :observability:bundle was found. The consumer was configured to find a runtime of a library compatible with Java 11, packaged as a jar, preferably optimized for standard JVMs, and its dependencies declared externally but:
          - None of the consumable configurations have attributes.

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at <https://help.gradle.org>

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See <https://docs.gradle.org/7.5.1/userguide/command_line_interface.html#sec:command_line_warnings>

BUILD FAILED in 449ms
c
Is this working now?
Copy code
./gradlew :observability:bundle:clean :observability:bundle:jar
e
from utils
Copy code
eric.kolotyluk@Y2RCV7009N access-ai % ./gradlew :observability:bundle:clean :observability:bundle:jar                                                               

FAILURE: Build failed with an exception.

* What went wrong:
Task 'clean' not found in project ':observability:bundle'.

* Try:
> Run gradlew tasks to get a list of available tasks.
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at <https://help.gradle.org>

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See <https://docs.gradle.org/7.5.1/userguide/command_line_interface.html#sec:command_line_warnings>

BUILD FAILED in 425ms
c
id 'java'
is redundant, included in application.
ok, let’s fix this issue first - the bundle project should apply
java-library
plugin, which provided a clean task.
e
Fixed, but same errors
c
is this working now?
./gradlew :observability:bundle:clean
e
Copy code
eric.kolotyluk@Y2RCV7009N access-ai % ./gradlew :observability:bundle:clean

FAILURE: Build failed with an exception.

* What went wrong:
Task 'clean' not found in project ':observability:bundle'.

* Try:
> Run gradlew tasks to get a list of available tasks.
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at <https://help.gradle.org>

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See <https://docs.gradle.org/7.5.1/userguide/command_line_interface.html#sec:command_line_warnings>

BUILD FAILED in 430ms
c
How about
./gradlew :observability:bundle:jar
?
e
Copy code
eric.kolotyluk@Y2RCV7009N access-ai % ./gradlew :observability:bundle:jar

FAILURE: Build failed with an exception.

* What went wrong:
Task 'jar' not found in project ':observability:bundle'.

* Try:
> Run gradlew tasks to get a list of available tasks.
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at <https://help.gradle.org>

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See <https://docs.gradle.org/7.5.1/userguide/command_line_interface.html#sec:command_line_warnings>

BUILD FAILED in 384ms
c
wowsers. not what is expected. Grab this output:
Copy code
./gradlew :observability:bundle:tasks --all
e
Copy code
eric.kolotyluk@Y2RCV7009N access-ai % ./gradlew :observability:bundle:tasks --all

> Task :observability:bundle:tasks

------------------------------------------------------------
Tasks runnable from project ':observability:bundle'
------------------------------------------------------------

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in project ':observability:bundle'.
dependencies - Displays all dependencies declared in project ':observability:bundle'.
dependencyInsight - Displays the insight into a specific dependency in project ':observability:bundle'.
help - Displays a help message.
javaToolchains - Displays the detected java toolchains.
outgoingVariants - Displays the outgoing variants of project ':observability:bundle'.
projects - Displays the sub-projects of project ':observability:bundle'.
properties - Displays the properties of project ':observability:bundle'.
resolvableConfigurations - Displays the configurations that can be resolved in project ':observability:bundle'.
tasks - Displays the tasks runnable from project ':observability:bundle'.

Other tasks
-----------
components - Displays the components produced by project ':observability:bundle'. [deprecated]
dependentComponents - Displays the dependent components of components in project ':observability:bundle'. [deprecated]
model - Displays the configuration model of project ':observability:bundle'. [deprecated]

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See <https://docs.gradle.org/7.5.1/userguide/command_line_interface.html#sec:command_line_warnings>

BUILD SUCCESSFUL in 404ms
1 actionable task: 1 executed
c
that’s…. an empty project. Check that the include paths are correct.
This include:
Copy code
include ':observability:bundle'
project(':observability').projectDir = file('../observability')
project(':observability:bundle').projectDir = file('../observability/bundle')
…is that the correct pathing? Is there a build.gradle in
../observability/bundle
?
all the other includes, including this commented out one, go up two directory levels:
Copy code
//include ':observability:bundle'
//project(':observability').projectDir = file('../../observability')
//project(':observability:bundle').projectDir = file('../../observability/bundle')
e
OMG... I keep making the same copy/paste mistakes over and over again...
The way we link projects together is INSANE
c
yes. The idiomatic approach is to have those as directories underneath the root project and not have to set projectDir.
e
I keep stressing to my boss we need a complete overhaul of how we are using Gradle
👍 1
Copy code
eric.kolotyluk@Y2RCV7009N access-ai % ./gradlew clean build

> Task :common-utils:compileJava
Note: /Users/eric.kolotyluk/git/autonomous-iam/utils/src/main/java/com/forgerock/autoid/utils/Mapper.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

> Task :event-lib:compileJava
Note: /Users/eric.kolotyluk/git/autonomous-iam/autonomous-commons/event-lib/src/main/java/com/forgerock/autoid/event/pubsub/PubSubHelper.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

> Task :service-commons:jandex
Index has been written to /Users/eric.kolotyluk/git/autonomous-iam/autonomous-commons/service-commons/build/resources/main/META-INF/jandex.idx

> Task :service-commons:jar
Execution optimizations have been disabled for task ':service-commons:jar' to ensure correctness due to the following reasons:
  - Gradle detected a problem with the following location: '/Users/eric.kolotyluk/git/autonomous-iam/autonomous-commons/service-commons/build/resources/main'. Reason: Task ':service-commons:jar' uses this output of task ':service-commons:jandex' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed. Please refer to <https://docs.gradle.org/7.5.1/userguide/validation_problems.html#implicit_dependency> for more details about this problem.

> Task :compileScala
'jvm-1.11' is not a valid choice for '-target'
bad option: '-target:jvm-1.11'

> Task :compileScala FAILED

FAILURE: Build completed with 2 failures.

1: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':compileScala'.
> Compilation failed

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
==============================================================================

2: Task failed with an exception.
-----------
* What went wrong:
java.lang.StackOverflowError (no error message)

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
==============================================================================

* Get more help at <https://help.gradle.org>

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See <https://docs.gradle.org/7.5.1/userguide/command_line_interface.html#sec:command_line_warnings>

Execution optimizations have been disabled for 1 invalid unit(s) of work during this build to ensure correctness.
Please consult deprecation warnings for more details.

BUILD FAILED in 24s
42 actionable tasks: 34 executed, 8 up-to-date
STACK OVERFLOW???
c
Copy code
> Task :compileScala
'jvm-1.11' is not a valid choice for '-target'
bad option: '-target:jvm-1.11'
e
You would think I could find that in our file system, and you would be wrong...
c
its either specifically set -
1.11
- or derived (incorrectly) from the Java 11 version that is set, which may indicate an older Scala plugin version.
e
Copy code
implementation "com.fasterxml.jackson.module:jackson-module-scala_2.12:${jacksonVersion}"
???
c
not seeing how that is related to a scala compile task?
e
I remember fighting this battle before, but cannot remember how I found it
There is no version on the scala plugin
c
it’s bundled with Gradle - is this now Gradle 7.5.1?
1
that’s likely what broke it, as several components stopped accepting the
1.x
qualified Java versions for anything after 1.8 (iirc). Anyhow, you’ll need to track down where the Scala JVM version is set and correct it.
Perhaps this or this are relevant.
e
This is really insane... I cannot figure out who is setting 'jvm-1.11' is not a valid choice for '-target'
c
looks like the introduction of toolchains trips this up. From issue, the options appear to be:
Copy code
update the dependency to 2.10.7, or
remove the toolchain definition and go back to the old block
e
Is there any way to explicitly tell the scala plugin what to do with the jvm target?
Our use of jackson with scala makes this so much harder... I now believe that scala in incompatible with Gradle...
Sorry, just getting really frustrated now...
Apparently
Copy code
scala {
    compileScala.targetCompatibility = 1.8
    ScalaCompileOptions.metaClass.useAnt = false
}
has no effect
This has no effect either
Copy code
tasks.withType(ScalaCompile) {
    scalaCompileOptions.with {
        sourceCompatibility = "1.8"
        targetCompatibility = '1.8'
    }
}
I am beginning to think the scala plugin I am using is broken... StackOverflow has many issues related to this, and I have been trying all the solutions
c
perhaps check the Scala version in the affected project (from that issue s/b 2.10.7+).
implementation 'org.scala-lang:scala-library:2.12.1'
e
I have set everything to 2.10.7, and that does not help
c
perhaps create a small, minimal project to reproduce this.
e
NOT GOING TO HAPPEN
c
Something like
Copy code
apply plugin: 'scala'

repositories {
    mavenCentral()
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(8)
    }
}

dependencies {
    implementation 'org.scala-lang:scala-library:2.10.4'
}
e
when I use java 8, it breaks all kinds of other things...
c
adjust as needed. point is to have a separate, reproducible project that you can explore options to resolve this in.
e
Apparently, there is no way to specify the version of the scala plugin to use. I believe the version I am using is broken
These kinds of scala plugin problems have been reported for over 3 years
Copy code
java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(8)
    }
}
results in
Copy code
eric.kolotyluk@Y2RCV7009N access-ai % ./gradlew clean build

FAILURE: Build failed with an exception.

* What went wrong:
Could not determine the dependencies of task ':copyLibs'.
> Could not resolve all task dependencies for configuration ':runtimeClasspath'.
   > Could not resolve project :service-commons.
     Required by:
         project :
      > No matching variant of project :service-commons was found. The consumer was configured to find a runtime of a library compatible with Java 8, packaged as a jar, preferably optimized for standard JVMs, and its dependencies declared externally but:
          - Variant 'apiElements' capability com.forgerock.autoid:service-commons:1.0-SNAPSHOT declares a library, packaged as a jar, and its dependencies declared externally:
              - Incompatible because this component declares an API of a component compatible with Java 11 and the consumer needed a runtime of a component compatible with Java 8
              - Other compatible attribute:
                  - Doesn't say anything about its target Java environment (preferred optimized for standard JVMs)
          - Variant 'mainSourceElements' capability com.forgerock.autoid:service-commons:1.0-SNAPSHOT declares a component, and its dependencies declared externally:
              - Incompatible because this component declares a component of category 'verification' and the consumer needed a library
              - Other compatible attributes:
                  - Doesn't say anything about its target Java environment (preferred optimized for standard JVMs)
                  - Doesn't say anything about its target Java version (required compatibility with Java 8)
                  - Doesn't say anything about its elements (required them packaged as a jar)
                  - Doesn't say anything about its usage (required a runtime)
          - Variant 'runtimeElements' capability com.forgerock.autoid:service-commons:1.0-SNAPSHOT declares a runtime of a library, packaged as a jar, and its dependencies declared externally:
              - Incompatible because this component declares a component compatible with Java 11 and the consumer needed a component compatible with Java 8
              - Other compatible attribute:
                  - Doesn't say anything about its target Java environment (preferred optimized for standard JVMs)
          - Variant 'testResultsElementsForTest' capability com.forgerock.autoid:service-commons:1.0-SNAPSHOT:
              - Incompatible because this component declares a component of category 'verification' and the consumer needed a library
              - Other compatible attributes:
                  - Doesn't say anything about how its dependencies are found (required its dependencies declared externally)
                  - Doesn't say anything about its target Java environment (preferred optimized for standard JVMs)
                  - Doesn't say anything about its target Java version (required compatibility with Java 8)
                  - Doesn't say anything about its elements (required them packaged as a jar)
                  - Doesn't say anything about its usage (required a runtime)

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at <https://help.gradle.org>

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See <https://docs.gradle.org/7.5.1/userguide/command_line_interface.html#sec:command_line_warnings>
c
Yes. Expected when other libs are compiled with Java 11.
e
Taking a lunch break for a while... I am super stressed out now...
As much as I hate SBT, it is the most reliable way to deal with Scala. I have had success using Maven with Scala, but only on the back-end. Maven cannot build a Scala front-end, only SBT can. I am still a Gradle newbie, but my impression is that the Gradle Scala plugin is not a serious product. There are too many complaints about the same things on StackOverflow and elsewhere, so whoever supports that code does not take it seriously.
Scala does not make life easy either, the lack of backwards compatibility forces everyone to use another layer of versions. At least SBT has some support for this.
c
btw, for all those includes with different paths - often find it helpful to have a utility function handle those, including validation of the paths, etc such that the boilerplate is minimized. One possible option below. Another option is to scan directories to include their projects (if there is a conventional layout).
Copy code
public fun Settings.includeProject(path: String) {
    if (path.contains("/") || path.contains("\\")) {
        throw GradleException("Invalid project path; must use ':' as project path separator")
    }
    val projectPath = when {
        path.startsWith(":") -> path
        else -> ":$path"
    }
    include(projectPath)
    val projectDesc = findProject(projectPath)
    check(projectDesc != null) { "Unable to resolve project @ path '$projectPath'" }
    val projectDir = File("../../" + projectPath.drop(1).replace(":","/"))
    check(projectDir.exists()) { "Project directory does not exist: $projectDir"}
    projectDesc.projectDir = projectDir
}

/*

### Original
include ':observability:bundle'
project(':observability').projectDir = file('../observability')
project(':observability:bundle').projectDir = file('../observability/bundle')

Could become:

includeProject(":observability:bundle")
 */
e
Great idea... both Groovy and Kotlin are programming languages after all...