jdaugherty opened a new pull request, #15948:
URL: https://github.com/apache/grails-core/pull/15948
## Description
Grails commands (`ApplicationCommand` implementations) have always shipped
inside runtime plugin
artifacts, dragging CLI-only dependencies onto application runtime
classpaths. This causes real
failures: `grails-shell-cli` leaks a conflicting Groovy onto the app
classpath (see the
long-standing exclusion + TODO in
`grails-data-hibernate{5,7}/dbmigration/build.gradle`), and a
CLI-only Spring Boot `WebApplicationInitializer` breaks classic WAR
deployment with an NPE
(#15377) unless users hand-filter the `bootWar` classpath.
(no classifiers or capability syntax for consumers), fully consumable by
Maven as well as Gradle.
### Framework changes
- **`grails-core-cli`**: the command contract moves from
`grails.dev.commands.*` to
`org.apache.grails.core.cli.*`. Command registrations move from
`META-INF/grails.factories` to a
dedicated `META-INF/grails-cli.factories`, written by a new
`CommandFactoriesTransformation`
that ships in the cli artifact (so it is active exactly when a command can
compile). The default
`grails-core` jar contains no command code and no command contract.
- **Companion artifacts** for all command-bearing modules, each with a
unique package and
`Automatic-Module-Name`: dbmigration (h5/h7, 29 `dbm-*` commands each),
the hibernate plugins
(`schema-export`), scaffolding (9 `generate-*` commands), web-url-mappings
(`url-mappings-report`), spring-security, and spring-security-oauth2.
`grails-shell-cli` is gone
from every runtime dependency graph.
- **BOM**: the base BOM enumerates and manages every companion coordinate.
### Build/tooling changes
- **New `org.apache.grails.gradle.grails-cli` plugin** (applied
automatically by the Grails
application/plugin plugins): registers the `grailsCli` configuration —
compile-visible for
`grails-app/commands` sources and on the command-runner and test
classpaths, but never on the
main `runtimeClasspath`, so commands and their CLI-only dependencies are
excluded from
`bootRun`/`bootJar`/`bootWar`. It auto-provisions `grails-core-cli` +
`grails-console`, and
**discovers plugin companions automatically**: a command-bearing plugin
advertises its companion
through a `Grails-Cli-Artifact` manifest attribute on its runtime jar, and
the plugin walks the
resolved dependency graph (including transitive plugins) and adds each
advertised companion to
`grailsCli`. Per-command Gradle tasks (`dbmUpdate`, …) register from the
discovered companions —
no `buildscript { classpath }` entry needed. Opt out with `grails {
cliAutoProvision = false }`.
The `console`/`shell` tasks draw from the same provisioned tier, so
generated apps no longer
declare `console "org.apache.grails:grails-console"`.
- **New `org.apache.grails.gradle.grails-plugin-cli` plugin** for plugin
authors (dogfooded by the
framework's own modules): one `apply` sets up the cli source set as a
feature variant, the
command contract on its compile classpath, the manifest advertisement, and
the companion
publication.
- **grails-publish**: builds on the additional-publications support added in
apache/grails-gradle-publish#34 (requires `grails-publish` ≥
`1.0.0-SNAPSHOT`; the version is
bumped in `dependencies.gradle`).
- **Forge/profiles**: generated apps declare only runtime plugins; all CLI
wiring is automatic.
### Consumer impact
Most applications upgrade with **no build changes**: declaring a
command-bearing plugin is enough,
and its commands (and Gradle tasks) follow automatically. Application
commands in
`grails-app/commands` only need the import rename (`grails.dev.commands.*` →
- [x] This PR contains a **single, focused change**.
- [x] This PR targets the **correct branch** for the type of change (`8.0.x`
— breaking changes are part of the major release).
### Code Quality
- [x] I have **added or updated tests** that cover the changes introduced in
this PR (module unit
suites, dbmigration integration tests, the config-report end-to-end
integration test
exercising the full discovery → factories → runner chain, forge
feature specs, and
grails-gradle plugin tests).
- [x] I have verified that all existing tests pass by running `./gradlew
build --rerun-tasks`.
- [x] My code follows the project's **code style** guidelines
(`aggregateViolations` reports zero
Checkstyle/CodeNarc/PMD/SpotBugs findings).
- [x] This PR does **not** include mass reformatting, style-only changes, or
large-scale refactoring
beyond the approved scope.
- [x] If generative AI tooling was used in preparing this contribution, a
quality model was used to ensure contributions are **consistent with the
project's quality standards**.
### Licensing and Attribution
- [x] All contributed code is provided under the Apache License 2.0, and new
source files include the **Apache license header**.
- [x] I have the necessary rights to submit this contribution.
- [x] If generative AI tooling was used in preparing this contribution, I
have followed the ASF policy on generative tooling and have properly attributed
its use.
### Documentation
- [x] User-facing changes are documented (Creating Custom Commands,
Providing Basic Artefacts,
Gradle plugins catalog, `create-command` reference).
- [x] The **What's New** section covers the companion `-cli` artifacts,
automatic discovery, and the new plugins.
- [x] The **Upgrade Notes** (section 33) cover the package renames, the
`grails-cli.factories`
clean break, the `grailsCli` configuration, and the third-party plugin
migration path.
- [x] The PR description clearly explains **what** was changed and **why**.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]