Init Script and Convention Plugins

I am using a project with a Convention Plugin to apply common logic between submodules. The project structure looks like this:

my-project/
├── buildSrc/
│   └── .../java-common.gradle # Here the 'java' plugin is applied
├── module-1/
│   └── build.gradle # Here the 'java-common' convention is applied
└── module-1/
    └── build.gradle # Here the 'java-common' convention is applied

This build succeeds fine locally. However, our CI system applies an init script aggregates SourceSets:

rootProject {
    // Define variable for subprojects to actually consider as "source"
    ext {
        coverageSourceProjects = ["module-1"]
    }

    afterEvaluate {
        task jacocoAggregateReport(type: JacocoReport) {
            // Gather execution data from all subprojects
            executionData fileTree(project.rootDir.absolutePath).include("**/build/jacoco/*.exec")

            println("Coverage sources: " + coverageSourceProjects)
            allprojects.each { project ->
                if (project.name in coverageSourceProjects && project.hasProperty("sourceSets")) {
                    sourceSets project.sourceSets.main
                }
            }
            reports {
                xml.enabled true
                html.enabled true
                csv.enabled false
            }
        }
    }
}

Since the InitScript executes before the buildSrc directory is evaluated and the java plugin gets applied, non of the modules have any SourceSets defined. Therefore, this init script errors out:

A problem occurred configuring root project 'my-project'.
> Could not get unknown property 'sourceSets' for project ':module-1' of type org.gradle.api.Project.

How can I evaluate the Init Script after the buildSrc plugin has compiled?

There are quite some bad practices in that snippet and fixing some might help with your issue.
For example, do not use afterEvaluate, instead use pluginManager.withPlugin to react to the plugin you want to use being applied.
Also don’t use eager task creation, but use task configuration avoidance, then the configuration of the task is done as late as possible and only if the task is actually going to be executed unless something else is disturbing.

But what is probably one of the major problems is, that you happily cross project boundaries when you really shouldn’t, but instead use safe cross-project publishing.

Actually you should probably not try to build that aggregation manually anyway, but simply use the built-in jacoco-aggregation plugin which does it in the right way.