The GitHub Actions job "CI" on grails-core.git/8.0.x has failed. Run started by GitHub user borinquenkid (triggered by borinquenkid).
Head commit for run: 3d3f4bbcff0314b3295f60e3432445318ceab032 / Scott Murphy <[email protected]> Register a generated auto-configuration where it is generated (#16224) * Register a generated auto-configuration where it is generated The class a beans closure compiles to is created during compilation and is not a source file anyone can open, so listing it in AutoConfiguration.imports required knowing both that it exists and what the compiler decided to call it. Not knowing either produced a plugin whose beans were silently never registered, which is a poor thing to ask an author to notice. The name is settled in createAutoConfigurationSibling and nowhere else, so that is where the entry is now written - into the compilation's target directory, beside the grails-plugin.xml and grails.factories that are already generated there. A module that keeps the file by hand keeps it, and nothing is generated beside it: two copies of one resource cannot both go into the jar, and folding the hand authored entries into a copy under the build directory would lose them as soon as anyone deleted the file they were written in. Such a module is warned at compile time when the generated class is missing from its file, so the silent case is gone either way, and deleting the file is what opts in. Hand-authored entries have to stay possible: a class from another jar, one annotated with a composed annotation, or one carrying no annotation at all - the imports file being the registration and @AutoConfiguration only supplying ordering. grails-databinding and the beans-dsl-plugin example no longer apply the autoconfiguration-imports convention plugin, which generated the same entries a second time. The beans-dsl example keeps it: what it registers is a standalone @GrailsBeans class, which is a source file its author can see and so is left to be registered by hand, as any other auto-configuration is. * Drop an entry for a class that is no longer generated The file was only ever added to. A descriptor that was renamed, deleted, or given a different autoConfigurationName left an entry naming a class that no longer exists, and Spring Boot does not start on an auto-configuration it cannot load. An incremental build is where this shows: the stale class file is cleaned and the entry that named it is not. An entry is now kept only while the class it names is still generated into the module's own output, which is what the scanning task this replaced recalculated every time. Anything the current compilation registered is kept regardless, since class generation runs in a later phase than this does - without that, two descriptors rebuilt together would each prune the other, neither class file having been written yet. The set is weakly keyed on the compilation, so it is per-build rather than per-JVM in a daemon that reuses one. The specification now compiles through to OUTPUT rather than stopping at CLASS_GENERATION. Stopping earlier wrote no class files at all, so the output directory it asserts against was empty and could not have shown any of this. * Drop the entry when nothing is left to generate the class Pruning ran only while writing, and writing happens only when a class is generated. A descriptor deleted outright, or left with no beans closure or an empty one, generates nothing and so said nothing about the entry naming the class it used to generate - a build that removed the class kept the entry, and Spring Boot does not start on an auto-configuration it cannot load. The rename covered before only passed because the class replacing it did the writing. Reconciling is now something the compilation does rather than something generating a class does: the global Grails transform, which runs for every source unit of a project and already writes generated metadata to the same directory, drops entries whose classes are no longer generated there. Names registered by the compilation in hand are kept, their class files being written in a later phase than any of this runs in. The file is deleted rather than left empty when the last entry goes, an imports file with nothing in it being a resource that says nothing. * Fix generated auto-configuration registration lifecycle * Persist a write that only drops a stale entry, and warn once Two things register the same descriptor in a standard compilation - the local transform, and the global one from the node metadata it leaves - and neither consequence of that was handled. Comparing the set about to be written against the pruned set rather than against what was on disk meant a call that only dropped a stale entry appeared to change nothing and wrote nothing, leaving on disk the entry it had just decided was naming a class that no longer exists. It is compared against the file's own contents now, which also makes the className check that followed it redundant. The missing hand-authored entry was reported by both, so one entry to add read as two problems. The warning is gated on the name not already having been registered by this compilation. Also restores the coverage for a descriptor that is named like one but does not extend Plugin: its closure is still compiled, onto the class itself, and nothing is registered for it - which is what pins the scope to the sibling generated for a plugin descriptor. * Reach the beans transform the way the registering already does compileBeansDsl loaded GrailsBeansASTTransformation reflectively and returned quietly if it was absent, while the registering a few lines above referenced that class and the imports writer directly. Only one of those can be describing the class path truthfully. It is the direct one: grails-core declares grails-beans-dsl api, which is what the guard's own comment gave as the reason the branch could never be taken. Left as it was, the guard caught a condition that the next statement would have failed on anyway. * Register the sibling under Groovy-Eclipse too A descriptor carrying @GrailsBeans explicitly was registered by neither path there. The local transform skipped its own write, the compiler configuration holding no directory it could trust; the global transform registers from node metadata, and the metadata is not set yet when it runs - the local transform is what sets it, and for an annotated descriptor that happens afterwards. Only the convention path, where the global transform compiles the closure itself, was covered. The global transform now seeds the directory it resolved onto every class of the source unit before anything is transformed, and the local transform prefers it over the compiler's own. That is the Eclipse resolution being passed in rather than reached for: it lives in grails-core, which grails-beans-dsl cannot depend on. With a directory it can trust, the local transform no longer skips. * Register the sibling once, where its name is settled The global transform registered from the node metadata the local transform leaves behind, which was the only way the name reached a directory resolved for Groovy-Eclipse. Seeding that directory the other way round, so the local transform writes to it, leaves this reading metadata that either was written moments earlier by a call that has already registered the same name, or - for a descriptor carrying @GrailsBeans, compiled after this runs - is not there at all. Neither case registers anything the local transform has not. Removing it is what the duplicate reporting fixed earlier came from, so that guard is now defence rather than the thing standing between one entry to add and two reports of it. Reconciling stays: it is not about a class being generated, but about entries for classes that are not. * Stop guarding a duplicate that one call site cannot produce Registering happens in exactly one place now, so the same name cannot reach the hand-authored branch twice in a compilation and the gate against that reported on nothing. Its specification passed with the gate taken out, which is the worse half of keeping it: a test that cannot fail reads as cover for a branch nobody is holding. What is left there is worth asserting, so the specification keeps the case and drops the claim about counting - a hand-authored file missing the generated class is told which name to add, and no second file is generated beside it. That one fails when the warning is removed. * Drop the metadata nothing reads, and cover the annotated entry path The generated name was put on the class node for the global transform to read, and the global transform no longer reads anything: the write and the constant were the only references left, and the constant still described carrying a name somewhere that stopped asking for it. The specification also only reached the sibling through the convention, where the global transform compiles the closure itself. A descriptor carrying the annotation takes the other entry path - the local transform runs after this one and writes to the directory seeded for it - and that path registering nothing is exactly what went unnoticed before. It is covered now, and fails when the registering is taken away from it. Also removes a duplicate import of SourceUnit that codeStyle does not object to. Report URL: https://github.com/apache/grails-core/actions/runs/33576592901 With regards, GitHub Actions via GitBox
